<?xml version="1.0" encoding="utf-8"?>






<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>Lucas&#39; blog</title>
        <link>https://x3ro.de/</link>
        <description></description>
        <generator>Hugo 0.128.2 https://gohugo.io/</generator>
        
            <language>en-US</language>
        
        
        
        
        <lastBuildDate>Sat, 17 Jan 2026 16:25:27 +0530</lastBuildDate>
        
            <atom:link rel="self" type="application/rss+xml" href="https://x3ro.de/rss.xml" />
        
        
            <item>
                <title>Ditching GitHub</title>
                <link>https://x3ro.de/ditching-github/</link>
                <guid isPermaLink="true">https://x3ro.de/ditching-github/</guid>
                <pubDate>Sat, 17 Jan 2026 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>While somewhat late to the party, I&rsquo;ve also decided to divest from GitHub for my code-hosting needs. Much has been written about why one might not feel comfortable on GitHub these days, and there are many good reasons to not use the platform:</p>
<ul>
<li>
<p>As many other companies embracing AI, Microsoft/GitHub are training their models based on code and other data that does not belong to them. For example, GitHub Copilot is trained exclusively on projects hosted on GitHub, and completely ignores copyleft licenses (see also <a href="https://sfconservancy.org/GiveUpGitHub/">GiveUpGithub</a>).</p>
</li>
<li>
<p>Microsoft is in strategic partnerships with companies like <a href="https://news.microsoft.com/source/2024/08/08/palantir-and-microsoft-partner-to-deliver-enhanced-analytics-and-ai-services-to-classified-networks-for-critical-national-security-operations/">Palantir</a> and <a href="https://www.theatlantic.com/technology/archive/2020/01/ice-contract-github-sparks-developer-protests/604339/">ICE</a>, thus actively contributing to (<a href="https://www.nytimes.com/2025/05/30/technology/trump-palantir-data-americans.html">AI-assisted</a>) human-rights violations in the US and across the globe.</p>
</li>
<li>
<p>Microsoft is perhaps <a href="https://bdsmovement.net/microsoft">the most complicit tech company</a> in Israel’s illegal apartheid regime and ongoing genocide against 2.3 million Palestinians in Gaza.</p>
</li>
<li>
<p>More generally, it makes sense for open source development not to be entirely dependant on the benevolence of one of the biggest tech companies on the planet.</p>
</li>
</ul>
<p>As a result, I will be deleting my data from GitHub. For practical reasons I will keep <a href="https://github.com/x3ro">my GitHub account</a> to be able to contribute to projects hosted there, but hope that will become unnecessary long-term. In the future I want to host my own public instance of <a href="https://forgejo.org/">Forgejo</a>, but for the time being I will be using <a href="https://codeberg.org/fresskoma">Codeberg</a>, which seems to be a good alternative.</p>
<p>If you&rsquo;re interested in some other takes on why it makes sense to move off of the platform, check out <a href="https://nilsnh.no/2024/07/15/divesting-from-github-and-going-self-hosted/">this</a> and <a href="https://tomscii.sig7.se/2024/01/Ditching-GitHub">this</a> post.</p>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Fixing slow TCP traffic over Tailscale</title>
                <link>https://x3ro.de/fixing-slow-tcp-traffic-over-tailscale/</link>
                <guid isPermaLink="true">https://x3ro.de/fixing-slow-tcp-traffic-over-tailscale/</guid>
                <pubDate>Thu, 08 Jan 2026 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>When making my home NAS reachable via Tailscale I experienced very slow TCP speeds, but only when uploading from the NAS and only when going through the Tailscale tunnel.</p>
<h3 id="the-journey">The journey</h3>
<p>I was trying to get some data from my NAS, and noticed that the connection seemed quite slow, around 8-10 MBit. I started out by making sure that this is not an issue with my internet connection. I ran the following from various machines on that network, and got consistent results:</p>
<pre tabindex="0"><code>$ docker run --rm moutten/speedtest-cli --accept-gdpr
Speedtest by Ookla

     Server: &lt;redacted&gt;
        ISP: &lt;redacted&gt;
    Latency:     1.65 ms   (0.04 ms jitter)
   Download:   389.15 Mbps (data used: 473.9 MB )
     Upload:   383.03 Mbps (data used: 425.9 MB )
Packet Loss:     0.0%
</code></pre><p>At first I suspected the issue was with my mounted SMB share, so I switched to SFTP and was seeing the same issues. I then tried to use <code>iperf3</code> to get more insights into whats going on. On the NAS, I ran the following to start an iperf3 server:</p>
<pre tabindex="0"><code>docker run -it --rm --network=host networkstatic/iperf3 -s
</code></pre><p>Then, from the remote machine, I ran the following tests. First, in the direction from the remote machine to the NAS, which showed good speeds:</p>
<pre tabindex="0"><code>$ iperf3 -c 100.101.102.104

Connecting to host 100.101.102.104, port 5201
[  5] local 100.85.100.101 port 56494 connected to 100.101.102.104 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  54.7 MBytes   459 Mbits/sec  102   1.04 MBytes
[  5]   1.00-2.00   sec  26.2 MBytes   220 Mbits/sec    4    297 KBytes
[  5]   2.00-3.00   sec  22.5 MBytes   189 Mbits/sec    0    343 KBytes
[  5]   3.00-4.00   sec  26.2 MBytes   220 Mbits/sec    0    391 KBytes
[  5]   4.00-5.00   sec  28.8 MBytes   241 Mbits/sec    0    437 KBytes
[  5]   5.00-6.00   sec  32.5 MBytes   273 Mbits/sec    0    482 KBytes
[  5]   6.00-7.00   sec  36.2 MBytes   304 Mbits/sec    0    529 KBytes
[  5]   7.00-8.00   sec  38.8 MBytes   325 Mbits/sec    0    576 KBytes
[  5]   8.00-9.00   sec  43.8 MBytes   367 Mbits/sec    0    622 KBytes
[  5]   9.00-10.00  sec  46.2 MBytes   388 Mbits/sec    0    669 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec   356 MBytes   299 Mbits/sec  106             sender
[  5]   0.00-10.01  sec   353 MBytes   296 Mbits/sec                  receiver
</code></pre><p>However, examining traffic in the other direction (note the <code>-R</code> in the iperf command) showed a very different picture, with slow and variable connection speeds as well as intermittent stalling (sometimes):</p>
<pre tabindex="0"><code>Connecting to host 100.101.102.104, port 5201
Reverse mode, remote host 100.101.102.104 is sending
[  5] local 100.85.100.101 port 37272 connected to 100.101.102.104 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  1.37 MBytes  11.5 Mbits/sec
[  5]   1.00-2.00   sec   803 KBytes  6.58 Mbits/sec
[  5]   2.00-3.00   sec   838 KBytes  6.87 Mbits/sec
[  5]   3.00-4.00   sec   620 KBytes  5.08 Mbits/sec
[  5]   4.00-5.00   sec   788 KBytes  6.45 Mbits/sec
[  5]   5.00-6.00   sec   680 KBytes  5.57 Mbits/sec
[  5]   6.00-7.00   sec  1.25 MBytes  10.5 Mbits/sec
[  5]   7.00-8.00   sec   548 KBytes  4.49 Mbits/sec
[  5]   8.00-9.00   sec   937 KBytes  7.67 Mbits/sec
[  5]   9.00-10.00  sec  1.08 MBytes  9.06 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.02  sec  9.00 MBytes  7.54 Mbits/sec   68             sender
[  5]   0.00-10.00  sec  8.79 MBytes  7.38 Mbits/sec                  receiver
</code></pre><p>Notably, this was not an issue over UDP:</p>
<pre tabindex="0"><code>$ iperf3 --udp --client 100.101.102.104 --bitrate 350M -R
Connecting to host 100.101.102.104, port 5201
Reverse mode, remote host 100.101.102.104 is sending
[  5] local 100.85.100.101 port 38418 connected to 100.101.102.104 port 5201
[ ID] Interval           Transfer     Bitrate         Jitter    Lost/Total Datagrams
[  5]   0.00-1.00   sec  41.7 MBytes   350 Mbits/sec  0.017 ms  0/35630 (0%)
[  5]   1.00-2.00   sec  41.7 MBytes   350 Mbits/sec  0.018 ms  21/35626 (0.059%)
[  5]   2.00-3.00   sec  41.7 MBytes   350 Mbits/sec  0.032 ms  0/35625 (0%)
[  5]   3.00-4.00   sec  41.7 MBytes   350 Mbits/sec  0.015 ms  0/35633 (0%)
[  5]   4.00-5.00   sec  41.7 MBytes   350 Mbits/sec  0.021 ms  0/35619 (0%)
[  5]   5.00-6.00   sec  41.7 MBytes   350 Mbits/sec  0.022 ms  0/35628 (0%)
[  5]   6.00-7.00   sec  41.7 MBytes   350 Mbits/sec  0.036 ms  0/35617 (0%)
[  5]   7.00-8.00   sec  41.7 MBytes   350 Mbits/sec  0.020 ms  59/35639 (0.17%)
[  5]   8.00-9.00   sec  41.7 MBytes   350 Mbits/sec  0.017 ms  0/35628 (0%)
[  5]   9.00-10.00  sec  41.7 MBytes   350 Mbits/sec  0.028 ms  0/35620 (0%)
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Jitter    Lost/Total Datagrams
[  5]   0.00-10.01  sec   418 MBytes   350 Mbits/sec  0.000 ms  0/356725 (0%)  sender
[  5]   0.00-10.00  sec   417 MBytes   350 Mbits/sec  0.028 ms  80/356265 (0.022%)  receiver
</code></pre><h3 id="the-solution">The solution</h3>
<p>So it turns out that Tailscale tunnels all of its traffic over UDP, which was easy to see running <code>tcpdump</code> on either of the machines running <code>iperf</code>. Not being very versed in networking, I&rsquo;m not really sure what&rsquo;s at play here specifically, but I think it&rsquo;s something along the lines of:</p>
<ol>
<li>UDP upstream from my connection is slightly lossy</li>
<li>TCP tunneled over UDP interprets dropped / missed packages as congestion, and throttles</li>
</ol>
<p>What helped in the end was to increase TCP socket buffers on my NAS:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo sysctl -w net.ipv4.tcp_rmem<span class="o">=</span><span class="s2">&#34;4096 131072 50000000&#34;</span>
</span></span><span class="line"><span class="cl">sudo sysctl -w net.ipv4.tcp_wmem<span class="o">=</span><span class="s2">&#34;4096 131072 50000000&#34;</span>
</span></span></code></pre></div><p>The specific values I decided based on <a href="https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/10/html/network_troubleshooting_and_performance_tuning/tuning-tcp-connections-for-high-throughput">this page</a>.</p>
<p>This worked okay for a comparatively low-latency scenario (~20ms). However, for higher latencies (&gt;100ms) the I saw very slow speeds and stalls once more. Using <a href="https://spawn-queue.acm.org/doi/10.1145/3012426.3022184">BBR congestion control</a> helped in that situation, which is apparently designed to work well for situations where TCP traffic is known to be tunneled. Unfortunately my NAS does not support it.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo sysctl -w net.ipv4.tcp_congestion_control<span class="o">=</span>bbr
</span></span><span class="line"><span class="cl">sudo sysctl -w net.core.default_qdisc<span class="o">=</span>fq
</span></span></code></pre></div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Photoview on a Synology NAS</title>
                <link>https://x3ro.de/photoview-on-a-synology-nas/</link>
                <guid isPermaLink="true">https://x3ro.de/photoview-on-a-synology-nas/</guid>
                <pubDate>Thu, 01 Jan 2026 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>Getting <a href="https://github.com/photoview/photoview">Photoview</a> to work properly on my Synology NAS was a bit of a hassle, so I&rsquo;m documenting it here for posterity.</p>
<div class="callout info">
  I won&rsquo;t go into detail here about how to <a href="https://davejansen.com/manage-docker-without-needing-sudo-on-your-synology-nas/">set up docker on a Synology NAS</a>. Also, I&rsquo;m using sqlite as the database, because everything else seemed like overkill for my use-case.
</div>
<p><strong>The problem:</strong> No matter how I mounted my photos, they were always mounted with <code>rwx</code> permissions only for the user. This didn&rsquo;t work for me because the photos weren&rsquo;t all owned by the same user. I&rsquo;m not sure what&rsquo;s at play here, but if I change the user ID of the <code>photoview</code> user to any of the user IDs on the host system, they were suddenly mounted with <code>rwx</code> permissions for the groups as well:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-dockerfile" data-lang="dockerfile"><span class="line"><span class="cl"><span class="k">FROM</span><span class="s"> photoview/photoview:2</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">USER</span><span class="s"> root</span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">RUN</span> usermod -u <span class="m">1026</span> photoview<span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span><span class="k">USER</span><span class="s"> photoview</span><span class="err">
</span></span></span></code></pre></div><p>After that, the <code>compose.yml</code> looks mostly like the default one from the Photoview devs:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">photoview-prepare</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">build</span><span class="p">:</span><span class="w"> </span><span class="l">.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">user</span><span class="p">:</span><span class="w"> </span><span class="l">root</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entrypoint</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="l">/bin/bash -c &#34;sleep 1 &amp;&amp; chown -R photoview /home/photoview/media-cache /home/photoview/database&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">cap_add</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">CHOWN</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;/etc/localtime:/etc/localtime:ro&#34;</span><span class="w"> </span><span class="c">## use local time from host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;/etc/TZ:/etc/timezone:ro&#34;</span><span class="w"> </span><span class="c">## use timezone from host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;${HOST_PHOTOVIEW_LOCATION}/storage:/home/photoview/media-cache&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;${HOST_PHOTOVIEW_LOCATION}/database:/home/photoview/database&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">photoview</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">build</span><span class="p">:</span><span class="w"> </span><span class="l">.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">stop_grace_period</span><span class="p">:</span><span class="w"> </span><span class="l">10s</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;127.0.0.1:40001:8000&#34;</span><span class="w"> </span><span class="c">## HTTP port (host:container)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">depends_on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">photoview-prepare</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">service_completed_successfully</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">security_opt</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">seccomp:unconfined</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">apparmor:unconfined</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">PHOTOVIEW_DATABASE_DRIVER</span><span class="p">:</span><span class="w"> </span><span class="l">${PHOTOVIEW_DATABASE_DRIVER}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">PHOTOVIEW_SQLITE_PATH</span><span class="p">:</span><span class="w"> </span><span class="l">${PHOTOVIEW_SQLITE_PATH}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">PHOTOVIEW_LISTEN_IP</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;0.0.0.0&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">PHOTOVIEW_LISTEN_PORT</span><span class="p">:</span><span class="w"> </span><span class="m">8000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;/etc/localtime:/etc/localtime:ro&#34;</span><span class="w"> </span><span class="c">## use local time from host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;/etc/TZ:/etc/timezone:ro&#34;</span><span class="w"> </span><span class="c">## use timezone from host</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;${HOST_PHOTOVIEW_LOCATION}/database:/home/photoview/database&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;${HOST_PHOTOVIEW_LOCATION}/storage:/home/photoview/media-cache&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;${HOST_PHOTOVIEW_MEDIA_ROOT}/foo:/photos/foo:ro&#34;</span><span class="w">
</span></span></span></code></pre></div><p>For completeness, here&rsquo;s also my <code>.env</code> file:</p>
<pre tabindex="0"><code>HOST_PHOTOVIEW_LOCATION=/volume1/docker/photoview
HOST_PHOTOVIEW_MEDIA_ROOT=/volume1/SecurePhotos

PHOTOVIEW_DATABASE_DRIVER=sqlite
PHOTOVIEW_SQLITE_PATH=/home/photoview/database/photoview.db

WATCHTOWER_POLL_INTERVAL=86400
WATCHTOWER_TIMEOUT=30s
WATCHTOWER_CLEANUP=true
</code></pre>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Axum: the trait `Handler&lt;_, ()&gt;` is not implemented for fn item</title>
                <link>https://x3ro.de/axum-the-trait-handler_-is-not-implemented-for-fn-item/</link>
                <guid isPermaLink="true">https://x3ro.de/axum-the-trait-handler_-is-not-implemented-for-fn-item/</guid>
                <pubDate>Sun, 25 Dec 2022 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>While playing around with Axum, I ran into the above-mentioned compile-time error. The underlying issue, in my case, was holding a type that&rsquo;s not <code>Send</code> across an <code>await</code>. Read on if you&rsquo;re interested in the details.</p>
<p>The full error message I was given was the following:</p>
<pre tabindex="0"><code>              .fallback(fallback_handler);
    |          -------- ^^^^^^^^^^^^^^^^ the trait `Handler&lt;_, ()&gt;` is not implemented for fn item `fn(Extension&lt;State&gt;, Request&lt;Body&gt;) -&gt; impl Future&lt;Output = impl IntoResponse&gt; {fallback_handler}`
	|          |
	|          required by a bound introduced by this call
    |
    = help: the trait `Handler&lt;T, S, B2&gt;` is implemented for `Layered&lt;L, H, T, S, B, B2&gt;`
</code></pre><p>The error message didn&rsquo;t help me in figuring out what&rsquo;s going on. The most confusing part was that the problem seemed to be caused by instantiating a struct I had just written, but I hadn&rsquo;t changed anything about the function signature or the return value.</p>
<p>My handler looked something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">async</span><span class="w"> </span><span class="k">fn</span> <span class="nf">fallback_handler</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Extension</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>: <span class="nc">Extension</span><span class="o">&lt;</span><span class="n">State</span><span class="o">&gt;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">request</span>: <span class="nc">Request</span><span class="o">&lt;</span><span class="n">Body</span><span class="o">&gt;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">impl</span><span class="w"> </span><span class="n">IntoResponse</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">errors</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="nb">Box</span><span class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[];</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// [...]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">	</span><span class="kd">let</span><span class="w"> </span><span class="n">tera</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">state</span><span class="p">.</span><span class="n">tera</span><span class="p">.</span><span class="n">lock</span><span class="p">().</span><span class="k">await</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// [...]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">	</span><span class="n">StatusCode</span>::<span class="no">OK</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Now, if you&rsquo;re familiar with <code>async</code> Rust, you might already see the problem. It&rsquo;s the same issue described in detail <a href="https://nathanleclaire.com/blog/2021/11/06/tokio/rust-dyn-stderrorerror-cannot-be-sent-between-threads-safely/">here</a>, namely that</p>
<ol>
<li><code>std::error::Error</code> is not <code>Send</code>, i.e. it cannot safely be sent between threads</li>
<li>Holding a non-Send type across an <code>await</code> results in a non-Send Future (<a href="https://stackoverflow.com/q/66061722/124257">explanation</a>)</li>
</ol>
<p>Axum&rsquo;s <code>Handler</code> type, however, requires the resulting Future to be <code>Send</code>, as can be seen <a href="https://github.com/tokio-rs/axum/blob/978ae6335862b264b4368e01a52177d98c42b2d9/axum/src/handler/mod.rs#L104">here</a>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">Handler</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">S</span><span class="p">,</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Body</span><span class="o">&gt;</span>: <span class="nb">Clone</span> <span class="o">+</span><span class="w"> </span><span class="nb">Send</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Sized</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">&#39;static</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="sd">/// The type of future calling this handler returns.
</span></span></span><span class="line"><span class="cl"><span class="sd"></span><span class="w">	</span><span class="k">type</span> <span class="nc">Future</span>: <span class="nc">Future</span><span class="o">&lt;</span><span class="n">Output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Response</span><span class="o">&gt;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Send</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">&#39;static</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// [...]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>So, long story short: <strong>don&rsquo;t try to hold non-Send types across <code>await</code> calls</strong> when you&rsquo;re writing an Axum handler.</p>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Continuous deployment setup with Gitlab CI</title>
                <link>https://x3ro.de/continuous-deployment-setup-with-gitlab-ci/</link>
                <guid isPermaLink="true">https://x3ro.de/continuous-deployment-setup-with-gitlab-ci/</guid>
                <pubDate>Thu, 11 Nov 2021 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>Continuous deployment (CD) is all the rage these days. And, if you ask me, it&rsquo;s a good feeling to push to a branch, wait for some time, and eventually see your changes in production. Getting this to work within the confines of Gitlab CI can be a little tricky, so I&rsquo;m going to share my preferred set-up in this post.</p>
<h2 id="pipeline-structure">Pipeline structure</h2>
<p>I&rsquo;ll be talking about the following scenario:</p>
<p><img src="/post-assets/gitlab-continuous-deployment/simple-graph.png" alt=""></p>
<p>The reason I would always include an intermediate environment (e.g. &ldquo;staging&rdquo;), is that I would need somewhere to run my automated acceptance tests<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> against, which try to make sure that the changes made do not brake any existing functionality. So in reality, the pipeline would look a little more like this:</p>
<p><img src="/post-assets/gitlab-continuous-deployment/complex-graph.png" alt=""></p>
<div class="callout info">
  TLDR: If the above scenario matches your needs, and you don&rsquo;t feel like reading, you can find the a runnable example pipeline <a href="https://gitlab.com/x3ro-de/gitlab-continuous-deployment-example">in this repository</a>.
</div>
<p>Looking at the part of the pipeline after the unit test stage (blue) completes, <strong>it looks the same for both staging and production</strong>. First we want to deploy to the stage, then run our acceptance tests against said stage.</p>
<p>As far as I&rsquo;m aware, for Gitlab pipeline definitions, we have three ways to handle this duplication:</p>
<ol>
<li><a href="https://yaml.org/type/merge.html">YAML anchors and merge key</a></li>
<li><a href="https://docs.gitlab.com/ee/ci/yaml/#extends">Gitlab CI <code>extends</code> directive</a></li>
<li><a href="https://docs.gitlab.com/ee/ci/pipelines/parent_child_pipelines.html">Gitlab CI child pipelines</a></li>
</ol>
<p>I won&rsquo;t go into detail about any of them, but I&rsquo;ve found (3) to be the one that I prefer. It allows me to (mostly) separate the &ldquo;deployment / acceptance test&rdquo; logic into its own building block, making it easy to, for example, add new stages without having to copy and paste boilerplate.</p>
<div class="callout info">
  Basic familiarity with how <a href="https://docs.gitlab.com/ee/ci/yaml/index.html">Gitlab CI definitions</a> work is assumed going forward.
</div>
<h2 id="the-parent-pipeline">The parent pipeline</h2>
<p>Okay, so let&rsquo;s look at some <code>.gitlab-ci.yml</code> (full source available <a href="https://gitlab.com/x3ro-de/gitlab-continuous-deployment-example/-/blob/main/.gitlab-ci.yml">here</a>). It starts out simple enough:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">stages</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="s2">&#34;Analyze/Test&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="s2">&#34;Deploy Staging&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="s2">&#34;Deploy Production&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">workflow</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># For jobs which contain `rules`, removing this causes strange behaviour</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># when merge requests are created. In that scenario, additional detached</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># pipeline runs are started.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># See also: https://gitlab.com/gitlab-org/gitlab/issues/34756#note_282820625</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">$CI_COMMIT_BRANCH</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">test</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">stage</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Analyze/Test&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">script</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">echo &#34;Running test suite ...&#34;</span><span class="w">
</span></span></span></code></pre></div><p>Not many surprises here, except for the <code>workflow</code> workaround (which will hopefully be fixed in the future). In this file you would add all stages that are independent of deployment, that is, <strong>all the checks that you wouldn&rsquo;t want to re-run for each stage you&rsquo;re deploying to</strong>. This would likely include your unit tests, integration tests, format checks, etc.</p>
<p>In addition, this is where we trigger the <a href="https://docs.gitlab.com/ee/ci/pipelines/parent_child_pipelines.html">child pipelines</a>, which will deploy to the individual environments:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">deploy_staging</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">stage</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Deploy Staging&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;$CI_COMMIT_BRANCH == &#34;main&#34;&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">when</span><span class="p">:</span><span class="w"> </span><span class="l">never</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">trigger</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">include</span><span class="p">:</span><span class="w"> </span><span class="l">.gitlab-ci/deploy-environment.yml</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">depend</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">variables</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">ENVIRONMENT_NAME</span><span class="p">:</span><span class="w"> </span><span class="l">staging</span><span class="w">
</span></span></span></code></pre></div><p>In the <code>rules</code> section we define that the deployment should only be run when updating the <code>main</code> branch. In <code>variables</code>, we pass whatever information is needed for the deployment, which in this example case is only the name. Finally, the <code>trigger</code> starts the child pipeline, in a way that the current (parent) pipeline will <code>depend</code> on the result.</p>
<div class="callout warning">
  <strong>Careful</strong>: If <code>strategy: depend</code> is omitted, the child pipeline would be started, but the parent would not wait for its completion. As a result, deployment to all environments would happen concurrently.
</div>
<h2 id="the-child-pipeline">The child pipeline</h2>
<p>Finally, the child pipeline we&rsquo;re triggering in the example above will be as simple or complex as your deployment / acceptance testing logic:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Contents of `.gitlab-ci/deploy-environment.yml`</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">stages</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">deploy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">acceptance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">deploy_static_environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">stage</span><span class="p">:</span><span class="w"> </span><span class="l">deploy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;$ENVIRONMENT_NAME&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">variables</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">WORKSPACE</span><span class="p">:</span><span class="w"> </span><span class="l">$CI_ENVIRONMENT_NAME</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;$CI_COMMIT_BRANCH == &#34;main&#34;&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">when</span><span class="p">:</span><span class="w"> </span><span class="l">never</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">script</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">echo &#34;Deploying $ENVIRONMENT_NAME&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">acceptance_tests_branch</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">stage</span><span class="p">:</span><span class="w"> </span><span class="l">acceptance</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">script</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">echo &#34;Deploying $ENVIRONMENT_NAME&#34;</span><span class="w">
</span></span></span></code></pre></div><p>Because we&rsquo;re triggering the child pipeline with <code>strategy: depend</code>, the parent will not continue to run until the child has completed successfully.</p>
<hr>
<p>You may think that this is a lot of effort for a relatively simple pipeline. And, if we&rsquo;re just looking at <a href="https://gitlab.com/x3ro-de/gitlab-continuous-deployment-example">the example I wrote</a>, I would agree. However, CI/CD pipelines tend to grow more complex over time, and, in my experience, a 1000+ line <code>.gitlab-ci.yml</code> file tends to be a bit cumbersome to understand, and especially to extend.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>The <a href="https://en.wikipedia.org/wiki/International_Software_Testing_Qualifications_Board">ISTQB</a> defines them as:</p>
<blockquote>
<p>Formal testing with respect to user needs, requirements, and business processes conducted to determine whether a system satisfies the acceptance criteria and [&hellip;] to determine whether to accept the system.</p>
</blockquote>
&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></li>
</ol>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Stand-alone testing a Spring security configuration</title>
                <link>https://x3ro.de/testing-spring-security-configuration/</link>
                <guid isPermaLink="true">https://x3ro.de/testing-spring-security-configuration/</guid>
                <pubDate>Wed, 10 Apr 2019 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>Many examples of testing Spring Security configurations out there focus on how to write an integration test covering your security configuration as well as your controller(s). This post examines one possible way of testing a security configuration in a (mostly) isolated fashion.</p>
<p>In a recent project I ran into a situation which had a relatively complex Spring Security configuration as well as some authorization logic sprinkled across it&rsquo;s controllers. In order to gain more confidence in refactoring the security configuration, I wanted an isolated test telling me whether my modifications also changed the configuration&rsquo;s behaviour. I came up with what&rsquo;s documented in this post.</p>
<hr>
<p>Let&rsquo;s start out by looking at the Spring Security configuration we&rsquo;ll be testing as part of this article:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Override</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">protected</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">configure</span><span class="p">(</span><span class="n">HttpSecurity</span><span class="w"> </span><span class="n">http</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">http</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">formLogin</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">and</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">logout</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">and</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">authorizeRequests</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">antMatchers</span><span class="p">(</span><span class="s">&#34;/secure/**&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">.</span><span class="na">authenticated</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">antMatchers</span><span class="p">(</span><span class="s">&#34;/admin/**&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">.</span><span class="na">hasRole</span><span class="p">(</span><span class="s">&#34;ADMIN&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">anyRequest</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">.</span><span class="na">permitAll</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Here we are setting up a form login and a logout page, and then proceed to say that there are three separate areas:</p>
<ul>
<li>A &ldquo;secure area&rdquo;, consisting of all sub-pages of <code>http://example.com/secure</code>. All logged in users can see this content</li>
<li>An admin area, containing all sub-pages of <code>http://example.com/admin</code>. Only users with the <code>ADMIN</code> role can see this content</li>
<li>Everything else, which is world accessible</li>
</ul>
<p>In order to test this configuration, I first created a dummy controller in my test code, which catches all <code>GET</code> requests:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Controller</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">DummyCatchAllController</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nd">@RequestMapping</span><span class="p">(</span><span class="n">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;/**&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">method</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">RequestMethod</span><span class="p">.</span><span class="na">GET</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nd">@ResponseBody</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="nf">catchAll</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="s">&#34;DummyCatchallController#catchAll&#34;</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Then I proceeded to set up a test which, using this dummy controller, tests the security configuration. First the boilerplate:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@RunWith</span><span class="p">(</span><span class="n">SpringJUnit4ClassRunner</span><span class="p">.</span><span class="na">class</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nd">@WebMvcTest</span><span class="p">(</span><span class="n">DummyCatchAllController</span><span class="p">.</span><span class="na">class</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nd">@Import</span><span class="p">({</span><span class="n">SecurityConfiguration</span><span class="p">.</span><span class="na">class</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">SecurityConfigurationTest</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">private</span><span class="w"> </span><span class="n">MockMvc</span><span class="w"> </span><span class="n">mockMvc</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nd">@Autowired</span><span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="n">WebApplicationContext</span><span class="w"> </span><span class="n">webApplicationContext</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nd">@Before</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">setup</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="na">mockMvc</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">MockMvcBuilders</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">.</span><span class="na">webAppContextSetup</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="na">webApplicationContext</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">.</span><span class="na">apply</span><span class="p">(</span><span class="n">springSecurity</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="o">[</span><span class="p">...</span><span class="o">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Instead of <code>@SpringBootTest</code> (loads your full application context) we&rsquo;re using <code>@WebMvcTest</code> (only loads whatever the controller needs) here, because they are commonly faster<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and we&rsquo;re trying to isolate the security configuration as much as possible. Since <code>WebMvcTest</code>s don&rsquo;t load the entire application context though, we need to manually import the security configuration with</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Import</span><span class="p">({</span><span class="n">SecurityConfiguration</span><span class="p">.</span><span class="na">class</span><span class="p">})</span><span class="w">
</span></span></span></code></pre></div><p>Next up, in the <code>setup</code> method, we&rsquo;re initializing MockMVC, which will help us perform our test requests against the controller. We cannot use the <code>@AutoConfigureMockMvc</code> annotation here, because we need to make sure that <code>springSecurity()</code> is applied, since that&rsquo;s what we want to test.</p>
<p>Now that we&rsquo;ve got the setup finished, we can finally look at the actual tests. If you&rsquo;re unfamiliar with how MockMVC works, and the examples are unclear, I recommend looking at <a href="https://spring.io/guides/gs/testing-web/">this introduction</a>.</p>
<p>First, let&rsquo;s make sure that our world-accessible resources can be seen by any user:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">asAnonymous_ICanAccessPublicResources</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">mockMvc</span><span class="p">.</span><span class="na">perform</span><span class="p">(</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;/foobar&#34;</span><span class="p">)).</span><span class="na">andExpect</span><span class="p">(</span><span class="n">status</span><span class="p">().</span><span class="na">isOk</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">mockMvc</span><span class="p">.</span><span class="na">perform</span><span class="p">(</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">)).</span><span class="na">andExpect</span><span class="p">(</span><span class="n">status</span><span class="p">().</span><span class="na">isOk</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Next, let&rsquo;s see if a loggged in user can see the &ldquo;secure area&rdquo;. Here we&rsquo;re using the <code>@WithMockUser</code> annotation to simulate a logged-in user who has the <code>USER</code> role.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nd">@WithMockUser</span><span class="p">(</span><span class="n">username</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;user&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">roles</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="s">&#34;USER&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">asLoggedInUser_ICanAccessSecureArea</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">mockMvc</span><span class="p">.</span><span class="na">perform</span><span class="p">(</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;/secure/foobar&#34;</span><span class="p">)).</span><span class="na">andExpect</span><span class="p">(</span><span class="n">status</span><span class="p">().</span><span class="na">isOk</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">mockMvc</span><span class="p">.</span><span class="na">perform</span><span class="p">(</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;/secure/&#34;</span><span class="p">)).</span><span class="na">andExpect</span><span class="p">(</span><span class="n">status</span><span class="p">().</span><span class="na">isOk</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>At the same time, we also want to make sure that a normal user can&rsquo;t see the admin area:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nd">@WithMockUser</span><span class="p">(</span><span class="n">username</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;user&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">roles</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="s">&#34;USER&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">asLoggedInUser_ICantAccessAdminArea</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">mockMvc</span><span class="p">.</span><span class="na">perform</span><span class="p">(</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;/admin/foobar&#34;</span><span class="p">)).</span><span class="na">andExpect</span><span class="p">(</span><span class="n">status</span><span class="p">().</span><span class="na">isForbidden</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">mockMvc</span><span class="p">.</span><span class="na">perform</span><span class="p">(</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;/admin/&#34;</span><span class="p">)).</span><span class="na">andExpect</span><span class="p">(</span><span class="n">status</span><span class="p">().</span><span class="na">isForbidden</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Finally, an admin <em>should</em> be able to see the admin area:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@Test</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nd">@WithMockUser</span><span class="p">(</span><span class="n">username</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;admin&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">roles</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="s">&#34;USER&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;ADMIN&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">public</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">asAdminUser_ICanAccessAdminArea</span><span class="p">()</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">mockMvc</span><span class="p">.</span><span class="na">perform</span><span class="p">(</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;/admin/foobar&#34;</span><span class="p">)).</span><span class="na">andExpect</span><span class="p">(</span><span class="n">status</span><span class="p">().</span><span class="na">isOk</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">mockMvc</span><span class="p">.</span><span class="na">perform</span><span class="p">(</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;/admin/&#34;</span><span class="p">)).</span><span class="na">andExpect</span><span class="p">(</span><span class="n">status</span><span class="p">().</span><span class="na">isOk</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Note that the usernames that we&rsquo;re supplying to the <code>@WithMockUser</code> annotation in all of these examples does not actually have any meaning. I&rsquo;ve only added it to make the test cases clearer.</p>
<p>That was it already. If you&rsquo;re interested in a runnable example to play around with, you can find it <a href="https://gitlab.com/x3ro-de/spring-security-configuration-test">here</a>.</p>
<br>
<div class="callout info">
    Feedback is always welcome and I try to incorporate it into the post where possible. For reasons of <a href="https://www.martinfowler.com/bliki/Datensparsamkeit.html">Datensparsamkeit</a> I do not provide a commenting solution here, however. You can reach me via email (see <a href="/">home page</a>) or <a href="http://twitter.com/fresskoma">Twitter</a>.
</div>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>See <a href="https://stackoverflow.com/a/39869110/124257">https://stackoverflow.com/a/39869110/124257</a> for more info&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Bochs with XQuartz on macOS</title>
                <link>https://x3ro.de/bochs-with-xquartz-on-macos/</link>
                <guid isPermaLink="true">https://x3ro.de/bochs-with-xquartz-on-macos/</guid>
                <pubDate>Thu, 29 Dec 2016 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>Installing Bochs on macOS is relatively straight forward with homebrew:</p>
<pre><code>$ brew cask install xquartz
$ brew install homebrew/x11/bochs
</code></pre>
<p>When trying to run it, I got the following error though</p>
<pre><code>Event type: PANIC
Device: [GUI   ]
Message: Cannot connect to X display
</code></pre>
<p>This happens because either XQuartz is not running or Bochs does not know how to communicate with it. You&rsquo;ll need to do two things:</p>
<ol>
<li>Start XQuartz.app
<ul>
<li>This will open an <code>xterm</code> terminal. Don&rsquo;t close it</li>
</ul>
</li>
<li>Now you have two options:
<ul>
<li>Run Bochs from within <code>xterm</code></li>
<li>Run <code>echo $DISPLAY</code> inside <code>xterm</code> and copy the result. Then run <code>export DISPLAY=&quot;&lt;copied string&gt;&quot;</code> in your normal terminal</li>
</ul>
</li>
<li>Either way, Bochs will now know which X display to connect to</li>
</ol>
<br>
<div class="callout info">
    Feedback is always welcome and I try to incorporate it into the post where possible. For reasons of <a href="https://www.martinfowler.com/bliki/Datensparsamkeit.html">Datensparsamkeit</a> I do not provide a commenting solution here, however. You can reach me via email (see <a href="/">home page</a>) or <a href="http://twitter.com/fresskoma">Twitter</a>.
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>On a scale from one to ten, …</title>
                <link>https://x3ro.de/on-a-scale-from-one-to-ten/</link>
                <guid isPermaLink="true">https://x3ro.de/on-a-scale-from-one-to-ten/</guid>
                <pubDate>Mon, 26 Jan 2015 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>Today we got a new intern (lets call him Tom), and while my colleague (that would be Jane) was trying to find a suitable task for him to get started with, I overheard a conversation similar to the following:</p>
<blockquote>
<p><strong>Jane</strong>: On a scale from one to ten, how proficient would you say you are in JavaScript?</p>
</blockquote>
<blockquote>
<p><strong>Tom</strong>: Uhm, not sure. I&rsquo;m not even sure what the numbers mean in this context.</p>
<p><strong>Jane</strong>: Well, it goes from &ldquo;I never heard of it&rdquo; to &ldquo;I know everything there is to know&rdquo;.</p>
<p><strong>Tom</strong>: I really can&rsquo;t say&hellip; Maybe a five?
&hellip;</p>
</blockquote>
<p>And I really feel for Tom. Not because he is only &ldquo;five good&rdquo; in JavaScript, but because I consider this whole &ldquo;How would you rate your <code>$foo</code> on a scale from <code>$bar</code> to <code>$baz</code>&rdquo; thing to be nonsense. Back in school, my physics teacher would always tell me how I must never forget the <em>units</em> in my calculations, because otherwise I wouldn&rsquo;t be able to <em>interpret</em> the result. But as it turns out, there is no unit for JavaScript knowledge, nor for any other programming language, because skill is very diffcult to quantify.</p>
<p>Let&rsquo;s take another look at why this or any other arbitrary scale is no good for skill (self-)assessment. We could assume that Tom was brought up in Spain, where the school system rates you from 1 (worst) to 10 (best). While in theory this could be a linear scale, in practice it is far from it: 1-4 means that you&rsquo;ve failed the class entirely and have to repeat it. The remainder is mapped as follows:</p>
<ul>
<li>5 ≡ sufficient</li>
<li>6 ≡ good</li>
<li>7-8 ≡ notable</li>
<li>9-10 ≡ outstanding</li>
</ul>
<p>As a result, Tom might be inclined to think that being &ldquo;five good&rdquo; in JavaScript signifies that you have only very basic knowledge of the language because this is consistent with how he&rsquo;s been graded his entire school career. Now we could assume that Jane was brought up in Germany where school grades are commonly 1 (best) through 6 (worst), with a 5 and a 6 indicating a failed class. Since this is not really compatible with our one-to-ten-scale, she might simply assume that skill level is distributed linearly. Both of their assumptions are visualized in the figure below, colors ranging from red (poor skill) through yellow (mediocre) to green (skilled).</p>
<img src="/post-assets/subjectivity-of-scales/tom-jane.svg" style="margin: auto; width: 85%; display: block;">
<p>Note that this interpretation of the scale is consistent with 1 meaning &ldquo;you&rsquo;ve never heard of it&rdquo; and 10 meaning &ldquo;I know everything there is know&rdquo;. The distribution in-between is very different though, such that being a &ldquo;five&rdquo; JavaScript coder for Jane would be roughly a &ldquo;seven&rdquo; for Tom, and so on. As a result, either Jane would think that Tom is massively overestimating himself or Tom would receive assignments that are way outside his own perceived skillset.</p>
<p>So now I&rsquo;ve critized the one-to-ten-scale. &ldquo;But which one should I use instead?&rdquo;, you ask. The answer could be: whichever you like, just keep the scale to yourself.</p>
<h4 id="using-binary-search-to-position-someone-on-a-scale-of-your-choice">Using binary search to position someone on a scale of your choice</h4>
<p>The thing is, that if you ask a question such as &ldquo;How good are you on a scale from [&hellip;]&rdquo;, then <strong>you</strong> already have an idea of what a &ldquo;seven&rdquo; (or any other number) means for a JavaScript programmer (at least in your own, very subjective scale). As a result, supposing that you are able to come up with a question for every number on your scale, you&rsquo;ll be able to position any person you encounter on any scale in about <code>log2(10)</code> steps (3.32, for the 1-10 scale), by using binary search starting from the middle of the scale. <br>For example:</p>
<pre><code>(1 2 3 4 5 6 7 8 9 10) - Pivot: 5. Answer: Correct
(          6 7 8 9 10) - Pivot: 8. Answer: Correct
(                9 10) - Pivot: 9. Answer: Incorrect
                       = Result: An 8
</code></pre>
<p>Since a scale is never communicated to the interviewee, no misunder­standings regarding the nature of the scale can arise. An additional benefit of this technique is that you can refine your questionnaire over time, based on your observations, thus gradually increasing the precision of your assessments. It should be noted that these must not be questions that can be memorized but could also be small programming excercises or the like, thus making this a viable technique for programming interviews as well. And it can even be automated!</p>
<p>What do you think about the one-to-ten-scale? Is it useful, and if so, in which situations? Could binary-search-based assessment be next big thing™?</p>
<br>
<div class="callout info">
    Feedback is always welcome and I try to incorporate it into the post where possible. For reasons of <a href="https://www.martinfowler.com/bliki/Datensparsamkeit.html">Datensparsamkeit</a> I do not provide a commenting solution here, however. You can reach me via email (see <a href="/">home page</a>) or <a href="http://twitter.com/fresskoma">Twitter</a>.
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Setting up the Xilinx Zynq based Zedboard for development</title>
                <link>https://x3ro.de/setting-up-the-xilinx-zynq-based-zedboard-for-development/</link>
                <guid isPermaLink="true">https://x3ro.de/setting-up-the-xilinx-zynq-based-zedboard-for-development/</guid>
                <pubDate>Fri, 16 Jan 2015 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>This blogpost should get you up and running if you want to develop applications for the Zedboard or another Xilinx Zynq-based platform without using the official SDKs (because let&rsquo;s be honest, it&rsquo;s pretty bloated!).</p>
<h2 id="requirements">Requirements</h2>
<p>I worked in an Ubuntu 14.10 virtual machine with OS X being the host operating system (which should not matter, I guess). Your experience may differ on other flavors of Linux.</p>
<p>Additionally you&rsquo;ll need to install <code>minicom</code> for initial communication with the board until an ethernet connection has been established as well as the toolchain to build applications for the target platform. Lastly <code>sshpass</code> will help us make testing our applications on the board a little easier. You can install all dependencies by running:</p>
<pre><code>sudo apt-get install gcc-4.9-arm-linux-gnueabihf minicom sshpass
</code></pre>
<h2 id="getting-the-board-up-and-running">Getting the board up and running</h2>
<p>I&rsquo;ve used the official <a href="http://www.wiki.xilinx.com/Zynq+Releases">Zynq Linux</a> 2014.4, which was the latest available version at the time. Download the release of your choice, extract the archive to an SD card and copy the <code>boot.bin</code> and <code>devicetree.dtb</code> files appropriate for your Zynq platform to the root of the SD card.</p>
<p>Now insert the SD card, connect the micro-usb cable to the UART port of your board and turn it on. If you&rsquo;re working on Linux there should now be a device named something like <code>/dev/ttyACM0</code>. You can connect to the board using minicom:</p>
<pre><code>sudo minicom -D /dev/ttyACM0
</code></pre>
<p>Note that you need root permissions for this operation. After connecting to the board you can then enter username and password (root/root by default) which gets you into a shell.</p>
<p>Next up is configuring your network interface. If you have a DHCP server at hand you can simply plug in the board and it&rsquo;ll receive an IP address which you can find out by running <code>ifconfig</code>. If, like me, you have the board directly connected to your computer it may be more convenient to configure a static IP address than to install a DHCP server (which this tutorial does not cover). You can achieve this by opening the <code>/etc/network/interfaces</code> file and replacing</p>
<pre><code>iface eth0 inet dhcp
</code></pre>
<p>with</p>
<pre><code>iface eth0 inet static
address 192.168.1.2
netmask 255.255.255.0
gateway 192.168.1.1
</code></pre>
<p>and subsequently running <code>ifdown eth0 &amp;&amp; ifup eth0</code>. Afterwards you should be able to SSH onto the board (don&rsquo;t forget to configure your network interface locally to have the IP 192.168.1.1).</p>
<h2 id="the-first-application">The first application</h2>
<p>Okay, now let&rsquo;s get the obligatory hello world application to run. I&rsquo;ve created a file <code>main.c</code> with the following content:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;hello world</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>To make our lives a little easier I&rsquo;ve written the following Makefile which builds the application, transfers it to the board and runs it, displaying the output and the exit code on the local machine.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-make" data-lang="make"><span class="line"><span class="cl"><span class="nv">BOARD_IP</span><span class="o">=</span>192.168.1.2
</span></span><span class="line"><span class="cl"><span class="nv">TARGET_DIR</span><span class="o">=</span>/home/root/
</span></span><span class="line"><span class="cl"><span class="nv">CC</span><span class="o">=</span>arm-linux-gnueabihf-gcc-4.9
</span></span><span class="line"><span class="cl"><span class="nv">LDFLAGS</span><span class="o">=</span>-static
</span></span><span class="line"><span class="cl"><span class="nv">CFLAGS</span><span class="o">=</span>-Wall -Wextra -O2 -std<span class="o">=</span>gnu99 -g -mcpu<span class="o">=</span>cortex-a9 -mfloat-abi<span class="o">=</span>hard
</span></span><span class="line"><span class="cl"><span class="nv">DEPS</span><span class="o">=</span>main.c
</span></span><span class="line"><span class="cl"><span class="nv">OBJ</span><span class="o">=</span>main.o
</span></span><span class="line"><span class="cl"><span class="nv">NAME</span><span class="o">=</span>hello-world
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">all</span><span class="o">:</span> <span class="k">$(</span><span class="nv">NAME</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">run</span><span class="o">:</span> <span class="k">$(</span><span class="nv">NAME</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">        sshpass -p root scp <span class="k">$(</span>NAME<span class="k">)</span> root@<span class="k">$(</span>BOARD_IP<span class="k">)</span>:<span class="k">$(</span>TARGET_DIR<span class="k">)</span> <span class="o">&amp;&amp;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>        sshpass -p root ssh root@<span class="k">$(</span>BOARD_IP<span class="k">)</span> <span class="s2">&#34;cd </span><span class="k">$(</span>TARGET_DIR<span class="k">)</span><span class="s2"> &amp;&amp; ./</span><span class="k">$(</span>NAME<span class="k">)</span><span class="s2">; echo &#39;Return code: &#39; </span><span class="nv">$$</span><span class="s2">?&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">%.o</span><span class="o">:</span> %.<span class="n">c</span> <span class="k">$(</span><span class="nv">DEPS</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">$(</span>CC<span class="k">)</span>  <span class="k">$(</span>CFLAGS<span class="k">)</span> -c -o <span class="nv">$@</span> $&lt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">$(NAME)</span><span class="o">:</span> <span class="k">$(</span><span class="nv">OBJ</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">$(</span>CC<span class="k">)</span> -o <span class="nv">$@</span> <span class="k">$(</span>CFLAGS<span class="k">)</span> <span class="k">$(</span>OBJ<span class="k">)</span> <span class="k">$(</span>LDFLAGS<span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">clean</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">        rm -f <span class="k">$(</span>NAME<span class="k">)</span> <span class="k">$(</span>OBJ<span class="k">)</span>
</span></span></code></pre></div><p>The output of <code>make run</code> the example source code should thus be:</p>
<pre><code>$ make run
hello world
Return code:  0
</code></pre>
<p>This concludes the &ldquo;getting up and running&rdquo; tutorial for the Zedboard (and similar Xilinx Zynq based platforms). If something doesn&rsquo;t work for you or if you have suggestions on how this tutorial can be improved, feel free to leave a comment or drop me an email.</p>
<br>
<div class="callout info">
    Feedback is always welcome and I try to incorporate it into the post where possible. For reasons of <a href="https://www.martinfowler.com/bliki/Datensparsamkeit.html">Datensparsamkeit</a> I do not provide a commenting solution here, however. You can reach me via email (see <a href="/">home page</a>) or <a href="http://twitter.com/fresskoma">Twitter</a>.
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Compiling &#34;Keen Dreams&#34; within DosBox on OS X</title>
                <link>https://x3ro.de/compiling-keen-dreams-within-dosbox-on-os-x/</link>
                <guid isPermaLink="true">https://x3ro.de/compiling-keen-dreams-within-dosbox-on-os-x/</guid>
                <pubDate>Thu, 18 Sep 2014 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>The &ldquo;Commander Keen in Keen Dreams&rdquo; <a href="https://github.com/keendreams/keen">source code</a> was released in September 2014 (see the <a href="https://news.ycombinator.com/item?id=8326883">Hacker News discussion</a>) and I wanted to see if I could compile it myself, and it turned out to be not that difficult!</p>
<p>For this excercise I used DosBox on OS X, but it should work on any platform that supports DosBox. The mount commands will probably look different if you&rsquo;re on Windows though.</p>
<h3 id="things-youll-need">Things you&rsquo;ll need</h3>
<ul>
<li><a href="http://www.dosbox.com/download.php">DosBox</a></li>
<li><a href="http://borlandc.org/download-borland-c-3-1/">Borland C++ 3.1</a></li>
<li><a href="https://github.com/keendreams/keen">Keen Dreams Source</a></li>
<li><a href="http://www.dosgamesarchive.com/download/commander-keen-dreams/">Shareware version of Keen Dreams</a> (for the game assets)</li>
</ul>
<h2 id="preparing-the-environment">Preparing the environment</h2>
<p>Download DosBox and copy it to your <code>Applications</code> folder. Then create a <code>DosBox</code> directory in your home directory (so the full path is <code>/Users/foobar/DosBox</code>) as well as a <code>C</code> and <code>D</code> directory inside it. Then go ahead and download Borland C++ 3.1 and extract it into the <code>A</code> directory.</p>
<div class="callout info">
  I picked a naming scheme where the directory names are identical to the mounted drives in DosBox so that I don&rsquo;t get confused <strong>(ノ^_^)ノ</strong> You can basically name them any way you want, just be sure to properly adapt the mount commands below.
</div>
<p>Now we start up DosBox for the first time. You&rsquo;ll see a prompt saying <code>Z:\</code> which is the only drive currently mounted, so we execute the following commands to mount our created directories as drives:</p>
<pre><code>Z:\&gt; mount A /Users/lucas/DosBox/A
Z:\&gt; mount C /Users/lucas/DosBox/C
Z:\&gt; mount D /Users/lucas/DosBox/D
</code></pre>
<p>Now we can install Borland C++ by switching to the <code>A:</code> drive and running <code>INSTALL.EXE</code>:</p>
<pre><code>Z:\&gt; A:
A:\&gt; INSTALL.EXE
</code></pre>
<p>Following the installation dialog and make sure to install Borland C++ into the <code>C:\BC2</code> directory, because that is where the &ldquo;Keen Dreams&rdquo; Borland project expects it to be installed:</p>
<img src="/post-assets/keen-dreams/borland-install.png" style="width: 100%" />
<p>Lastly we need to adjust the <code>PATH</code> environment variable so that the OS knows where to find the Borland binaries. We do this by running <code>SET PATH=Z:\;C:\BC2\BIN</code>. It also contains the <code>Z:\</code> drive because that is where DosBox stores its binaries! Running <code>BC</code> should now yield the following screen (which you can exit with <code>Alt-X</code>):</p>
<img src="/post-assets/keen-dreams/borland.png" style="width: 100%" />
<h2 id="compiling-the-source">Compiling the source</h2>
<p>The rest is pretty straight forward. First we need to create the <code>MAKEOBJ.EXE</code> inside the <code>STATIC</code> directory, which is later used to build some of the game&rsquo;s static files. To do this, run the following:</p>
<pre><code>A:\&gt; D:
D:\&gt; CD KEEN\STATIC
D:\&gt; BC MAKEOBJ.C
</code></pre>
<p>This will open Borland C++ with the specified file opened. Now press <code>F9</code> to compile and link it, thus creating <code>MAKEOBJ.EXE</code>. Exit Borland by pressing <code>Alt+X</code>. Now run <code>MAKE.BAT</code> in the same directory.</p>
<p>We&rsquo;ve now created the static files, but the game remains to be compiled. So we move on directory up (<code>CD ..</code>) and run <code>BC</code> again. This should automatically find the Keen Dreams project file and open it. Now press <code>F9</code> again, which builds the project. If everything works as expected, you&rsquo;ll now have a <code>KDREAMS.EXE</code> binary in your source directory.</p>
<h2 id="cant-open-kdreamsmap">Can&rsquo;t open KDREAMS.MAP</h2>
<p>Unfortunately, as with many games that are open-sourced, the actual game content is still licensed differently and is thus not included with the source. As a result, you&rsquo;ll see a <code>Can't open KDREAMS.MAP</code> error message when you try to start the compiled binary:</p>
<img src="/post-assets/keen-dreams/kdreams-map.png" style="width: 100%" />
<p>In order to run the game, you can download the assets from the shareware version of the game, though. Unpack the downloaded game and copy the following files to the Keen Dreams source directory (this is easier when done from outside DosBox):</p>
<pre><code>KDREAMS.AUD, KDREAMS.CMP, KDREAMS.EGA, KDREAMS.MAP
</code></pre>
<p>And voilà, you can now run the game. Have fun playing or fiddling around with the source :)</p>
<img src="/post-assets/keen-dreams/game-running.png" style="width: 100%" />
<br>
<div class="callout info">
    Feedback is always welcome and I try to incorporate it into the post where possible. For reasons of <a href="https://www.martinfowler.com/bliki/Datensparsamkeit.html">Datensparsamkeit</a> I do not provide a commenting solution here, however. You can reach me via email (see <a href="/">home page</a>) or <a href="http://twitter.com/fresskoma">Twitter</a>.
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Oh my god! My blog takes 50 seconds to load...</title>
                <link>https://x3ro.de/oh-my-god-my-blog-takes-50-seconds-to-load.../</link>
                <guid isPermaLink="true">https://x3ro.de/oh-my-god-my-blog-takes-50-seconds-to-load.../</guid>
                <pubDate>Sun, 16 Mar 2014 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>&hellip; on a 56k modem (<a href="https://www.youtube.com/watch?v=p8XKhCfsTts">remember those?</a>). Okay, that might not be a valid benchmark nowadays. But the fact that the homepage of my blog, without any real content, was weighing in at almost 350KB did startle me a little. Why? Because, you know, that&rsquo;s 50% the size of &ldquo;Zelda: A link to the Past&rdquo;, one of my favorite SNES game I spent countless hours playing, or about the size of Commander Keen, one of the first video games I&rsquo;ve ever played. Compared to these really awesome bytes, the bytes of my homepage should really be ashamed of themselves, so let&rsquo;s get rid of them. But where do they even come from?</p>
<img src="http://chart.googleapis.com/chart?chs=425x200&chd=t:131,91,85,15,14,4,4&cht=p3&chco=F5634A,FAD089&chl=Bootstrap|jQuery|Webfonts|Modernizr|Prettify.js|My+CSS|Content" class="center" />
<p>So roughly 2/3 of my blog&rsquo;s assets are basically.. junk. Not in general, but certainly for my use case. While Bootstrap might be nice, it&rsquo;s certainly overkill for a small blog. And jQuery? I&rsquo;m not even using that <em>anywhere</em>. I&rsquo;d argue that Prettify.js is justifiable, because nobody wants to read non-highlighted source code, right? And those web fonts? We&rsquo;ll see if they&rsquo;re worth the additional 80KB.</p>
<h2 id="how-did-it-come-to-this">How did it come to this?</h2>
<p>When I created the blog layout, I was being utterly lazy. I snatched up Twitter Bootstrap and jQuery, added some web fonts, mixed in a little CSS of my own, shook it around a little and done was my blog layout. Did I think about how much unnecessary stuff I was adding? Hell no!</p>
<p>Honestly, thinking about this made me a little sad. When developing for a customer, you can&rsquo;t always strive for perfection. There are deadlines, requirements and so on (you know the deal) and you usually have to stop somewhere and say &ldquo;This will work, even though it could be better&rdquo;. But for personal projects, this does not apply, so being sloppy is really not justifiable.</p>
<h2 id="lets-take-out-the-trash">Let&rsquo;s take out the trash!</h2>
<p>So I set out to dramatically reduce the loading size of my blog. First off, I tried to simply removed Bootstrap, jQuery and Modernizr and see how it goes. You know what? It didn&rsquo;t look that much different, but reduced the size from 350KB to around 100KB. See for yourself:</p>
<p><img src="/post-assets/ohmigod-size/before-after-site.png" alt=""></p>
<p>It&rsquo;s not identical, but we just reduced page size by about seventy percent, which seems quite acceptable.</p>
<p>This is not what you would encounter on a large web application, of course. If I had used many of the Bootstrap components, it might have actually been worth to keep, because development time is usually costlier than a few dozen extra kilobytes. And as for jQuery: it&rsquo;s an awesome library, and nobody really wants to deal with all the browser quirks and discrepancies that jQuery handles for you. But if you just have a couple of lines of JavaScript on your blog, chances are you simply don&rsquo;t need it.</p>
<h2 id="web-fonts">Web Fonts</h2>
<p>The remaining large portion of possibly superfluous bytes were the web fonts at around 80KB, &ldquo;PT Serif&rdquo; for the body text and &ldquo;Lato&rdquo; for headlines, both served by Google Fonts. At first I thought that they&rsquo;d be worth keeping, because reading an article in a nice font is so much more enjoyable. End then I found out that one of my favorite fonts is available on around 75% of all Windows and Mac system: Baskerville (chances are you&rsquo;re seeing it right now). So I used <a href="http://cssfontstack.com/">CSS Font Stack</a> to get a recommendation on fall-back fonts for Baskerville and was satisfied by how they look. I followed the same procedure for Lato, and thus was able to replace both web fonts.</p>
<h2 id="some-more-tweaking">Some more tweaking</h2>
<p>I mentioned that I wanted to keep Prettify.js for syntax highlighting. But why load it if it isn&rsquo;t used? So I made it optional per blog post. Oh, and <a href="http://pngquant.org/">pngquant</a> helped me reduce the size of my picture by 50%, removing another 3KB.</p>
<h2 id="the-status-quo">The Status Quo</h2>
<p>In summary, I managed to reduce the loading size of my blog&rsquo;s homepage from initially 350KB to almost 10KB without (visually) sacrificing anything but the web fonts, and I&rsquo;m fairly satisfied by the result. Let&rsquo;s take a look:</p>
<table style="width: 100%">
    <tr>
        <th>Before</th>
        <th>After</th>
    </tr>
    <tr>
        <td>
            <img class="center" src="http://chart.googleapis.com/chart?chs=240x80&chd=t:131,91,85,15,14,4,4&cht=p3&chco=F5634A,FAD089&chl=Bootstrap|jQuery|Webfonts|Modernizr|Prettify.js|My+CSS|Content" />
        </td>
        <td>
            <img class="center" src="http://chart.googleapis.com/chart?chs=300x80&chd=t:4,2.5,2.5&cht=p3&chco=F5634A,FAD089&chl=My+picture+(4KB)|CSS+(2.5KB)|Content+(2.5KB)" />
        </td>
    </tr>
</table>
<p>So what can we take away from this? It should once again remind us that there is no &ldquo;one size fits all&rdquo; solution. Every technology, framework and library has its place, but I&rsquo;d argue that the following approach is the road to a heap of technical debt and maintenance misery:</p>
<blockquote>
<p>In my last project I used Bootstrap, jQuery and [20 other cool things], so let&rsquo;s add those and see what we can do with them.</p>
</blockquote>
<p>Instead, ask yourself what you are trying to achieve and pick whatever fits the problem you&rsquo;re trying to solve.</p>
<br>
<div class="callout info">
    Feedback is always welcome and I try to incorporate it into the post where possible. For reasons of <a href="https://www.martinfowler.com/bliki/Datensparsamkeit.html">Datensparsamkeit</a> I do not provide a commenting solution here, however. You can reach me via email (see <a href="/">home page</a>) or <a href="http://twitter.com/fresskoma">Twitter</a>.
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Linking assembly with C on OS X</title>
                <link>https://x3ro.de/linking-assembly-with-c-on-os-x/</link>
                <guid isPermaLink="true">https://x3ro.de/linking-assembly-with-c-on-os-x/</guid>
                <pubDate>Thu, 12 Sep 2013 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>This is easy if you know how to do it, but it can be a pain to search for if you don&rsquo;t, so here&rsquo;s a short how-to.</p>
<p>First of all, we&rsquo;ll want to write a bit of C code which will invoke our assembly routine:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="kt">int</span> <span class="nf">my_pow</span><span class="p">(</span><span class="kt">int</span> <span class="n">base</span><span class="p">,</span> <span class="kt">int</span> <span class="n">exp</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="k">const</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">base</span><span class="p">,</span> <span class="n">exp</span><span class="p">,</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">base</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">exp</span> <span class="o">=</span> <span class="mi">8</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="nf">my_pow</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">8</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Result: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Using <code>clang</code> on Mac OS X (you should&rsquo;ve the latest Xcode installed), you can compile (but not link) this piece of code using the command</p>
<pre><code>clang -o test.o -c test.c
</code></pre>
<p>This assumes that your C source file is called <code>test.c</code>. Clang&rsquo;s <code>-c</code> compiles the given source file to an object file for later linking, and defaults to 64-bit mode. If you&rsquo;d rather create a 32-bit object file, you can supply the <code>-arch i386</code> parameter.</p>
<p>So now we&rsquo;ve compiled our C source, so it&rsquo;s time to write some assembly. But how does the C function pass the parameters, and how do we return the result? To answer such questions, it is often useful to look at the assembly generated from our C code, which can be obtained with <code>clang -S test.c</code>. The interesting part is the following (this is <a href="http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htm">AT&amp;T syntax</a>):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-asm" data-lang="asm"><span class="line"><span class="cl"><span class="nf">movl</span>    <span class="no">$2</span><span class="p">,</span> <span class="nv">%eax</span>
</span></span><span class="line"><span class="cl"><span class="nf">movl</span>    <span class="no">$8</span><span class="p">,</span> <span class="nv">%ecx</span>
</span></span><span class="line"><span class="cl"><span class="na">...</span>
</span></span><span class="line"><span class="cl"><span class="nf">movl</span>    <span class="nv">%eax</span><span class="p">,</span> <span class="nv">%edi</span>
</span></span><span class="line"><span class="cl"><span class="nf">movl</span>    <span class="nv">%ecx</span><span class="p">,</span> <span class="nv">%esi</span>
</span></span><span class="line"><span class="cl"><span class="nf">callq</span>   <span class="no">_my_pow</span>
</span></span><span class="line"><span class="cl"><span class="na">...</span>
</span></span><span class="line"><span class="cl"><span class="nf">movl</span>    <span class="nv">%eax</span><span class="p">,</span> <span class="p">-</span><span class="mi">28</span><span class="p">(</span><span class="nv">%rbp</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nf">movl</span>    <span class="p">-</span><span class="mi">28</span><span class="p">(</span><span class="nv">%rbp</span><span class="p">),</span> <span class="nv">%esi</span>
</span></span><span class="line"><span class="cl"><span class="nf">movb</span>    <span class="no">$0</span><span class="p">,</span> <span class="nv">%al</span>
</span></span><span class="line"><span class="cl"><span class="nf">callq</span>   <span class="no">_printf</span>
</span></span></code></pre></div><p>So our operands, 2 and 8, are moved into <code>eax</code> and <code>ecx</code> respectively, which are <a href="http://en.wikipedia.org/wiki/X86_calling_conventions#Intel_ABI">free-for-use registers</a>. In 32-bit C functions, operands are passed on the stack, but in the <a href="http://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI">System V AMD64 ABI</a> the first integer or pointer operands are passed in registers instead. As a result, our operands are moved to <code>edi</code> and <code>esi</code>, and our <code>_my_pow</code> procedure is called. The return value of the procedure is always stored in the <code>eax</code> (or <code>rax</code>) register.</p>
<div class="callout info">
  The Intel architecture reference can be found <a href="http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html">here</a>. A short overview of the x64 instructions and ABI is available <a href="http://www.classes.cs.uchicago.edu/archive/2009/spring/22620-1/docs/handout-03.pdf">here</a>. Additionally, the <a href="http://en.wikipedia.org/wiki/X86-64#Architectural_features">x86-64 Wikipedia article</a> gives a nice overview of available registers.
</div>
<p>So now it&rsquo;s time to write some assembly (this is <a href="http://en.wikibooks.org/wiki/X86_Assembly/NASM_Syntax">NASM Syntax</a> now, which uses the Intel assembly style):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nasm" data-lang="nasm"><span class="line"><span class="cl"><span class="k">global</span> <span class="nv">_my_pow</span>
</span></span><span class="line"><span class="cl"><span class="k">section</span> <span class="nv">.text</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nl">_my_pow:</span>
</span></span><span class="line"><span class="cl">    <span class="nf">push</span>    <span class="nb">rbp</span>             <span class="c1">; create stack frame</span>
</span></span><span class="line"><span class="cl">    <span class="nf">mov</span>     <span class="nb">rbp</span><span class="p">,</span> <span class="nb">rsp</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nf">cmp</span>     <span class="nb">edi</span><span class="p">,</span> <span class="mi">0</span>          <span class="c1">; Check if base is negative</span>
</span></span><span class="line"><span class="cl">    <span class="nf">mov</span>     <span class="nb">eax</span><span class="p">,</span> <span class="mi">0</span>          <span class="c1">; and return 0 if so</span>
</span></span><span class="line"><span class="cl">    <span class="nf">jl</span>      <span class="nv">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nf">mov</span>     <span class="nb">eax</span><span class="p">,</span> <span class="nb">edi</span>        <span class="c1">; grab the &#34;base&#34; argument</span>
</span></span><span class="line"><span class="cl">    <span class="nf">mov</span>     <span class="nb">edx</span><span class="p">,</span> <span class="nb">esi</span>        <span class="c1">; grab the &#34;exponent&#34; argument</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nl">multiply:</span>
</span></span><span class="line"><span class="cl">    <span class="nf">imul</span>    <span class="nb">eax</span><span class="p">,</span> <span class="nb">edi</span>        <span class="c1">; eax * base</span>
</span></span><span class="line"><span class="cl">    <span class="nf">sub</span>     <span class="nb">esi</span><span class="p">,</span> <span class="mi">1</span>          <span class="c1">; exponent - 1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nf">cmp</span>     <span class="nb">esi</span><span class="p">,</span> <span class="mi">1</span>          <span class="c1">; Loop if exponent &gt; 1</span>
</span></span><span class="line"><span class="cl">    <span class="nf">jg</span>      <span class="nv">multiply</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nl">end:</span>
</span></span><span class="line"><span class="cl">    <span class="nf">pop</span>     <span class="nb">rbp</span>             <span class="c1">; restore the base pointer</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ret</span>                     <span class="c1">; return from procedure</span>
</span></span></code></pre></div><p>First of all, we have to define the <code>_my_pow</code> label to be global, because otherwise C won&rsquo;t be able to call it. Note the underscore, since the C convention is to prepend one to all function labels. The &ldquo;create stack frame&rdquo; and &ldquo;restore base pointer&rdquo; parts are actually not necessary for our use case, since we do not use the stack, but I&rsquo;ve added them for completeness.</p>
<p>As we&rsquo;ve previously seen in the assembly generated from our C code, the &ldquo;base&rdquo; argument is passed in the <code>edi</code> register, and the &ldquo;exponent&rdquo; argument is passed in the <code>esi</code> register, so we start by moving the base to the result register <code>eax</code>, and then multiply <code>eax</code> and the base <code>exponent - 1</code> times.</p>
<p>Assuming that you saved the assembly under the name <code>asm.s</code>, you can now generate an object file using the following NASM command, which will generate an <code>asm.o</code> object file:</p>
<pre><code>nasm -f macho64 asm.s
</code></pre>
<p>After having generated both object files, you can now link them by invoking</p>
<pre><code>clang -o pow asm.o test.o
</code></pre>
<p>This should generate an executable called <code>pow</code>, which prints &ldquo;Result: 256&rdquo;. For reference, <a href="https://gist.github.com/x3ro/6536703">here are my resulting files</a>, including a simple Makefile.</p>
<br>
<div class="callout info">
    Feedback is always welcome and I try to incorporate it into the post where possible. For reasons of <a href="https://www.martinfowler.com/bliki/Datensparsamkeit.html">Datensparsamkeit</a> I do not provide a commenting solution here, however. You can reach me via email (see <a href="/">home page</a>) or <a href="http://twitter.com/fresskoma">Twitter</a>.
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>Integrating a submodule into the parent repository</title>
                <link>https://x3ro.de/integrating-a-submodule-into-the-parent-repository/</link>
                <guid isPermaLink="true">https://x3ro.de/integrating-a-submodule-into-the-parent-repository/</guid>
                <pubDate>Sun, 01 Sep 2013 00:00:00 +0000</pubDate>
                
                
                
                    <description><![CDATA[<p>Git submodules can be very useful, and there are many guides on how to extract a certain directory of your repository and make it a submodule, while preserving history. This post is about the opposite operation – re-integrating a submodule into the parent repository without <strong>loosing any history</strong>.</p>
<p>If you don&rsquo;t care about your history, simple use one of the solutions proposed in this <a href="http://stackoverflow.com/a/1789374/124257">Stackoverflow question</a>.</p>
<p>In said question, there actually is an answer that preserves history, but it has a major flaw: paths from the submodule aren&rsquo;t correctly updated, thus making the history less useful. Let&rsquo;s say you have the following repository structure:</p>
<pre><code>•
├── Makefile
├── lib/ (submodule)
│   └── bar.c
└── src/
    └── foo.c
</code></pre>
<p>If you try to merge this submodule or use <code>git subtree add</code> without modifications to the submodule, you&rsquo;ll end up with commits like this:</p>
<pre><code>commit 9f28e08ec8e1ae15823ec7ecb24bdf442a2d3581
Author: Lucas
Date:   Thu Aug 15 10:35:20 2013 +0200

    Do awesome stuff in submodule

diff --git a/bar.c b/bar.c
index b7c5cb8..997e3bb 100644
[...]
</code></pre>
<p>As you can see, the paths haven&rsquo;t been updated, and the commit still points to the path where <code>bar.c</code> resided in the submodule. This is problematic, because <code>git log lib/bar.c</code> will not show the commits made in the submodule. In order to fix this, we&rsquo;ll need to rewrite every commit made in the submodule, correcting the directory. The good news: git provides a tool for that: <code>git filter-branch</code> attached. The bad news: using filter-branch isn&rsquo;t exactly straight forward.</p>
<p>But fear not! I&rsquo;ve written a little bash script that&rsquo;ll do all the heavy lifting for you, if you don&rsquo;t want to get into the nitty-gritty details (download at the end of the post).</p>
<div class="callout warning">
  <strong>Warning:</strong> I&rsquo;ll suggest that you do both a clean clone of the parent repository and the submodule before you proceed.
</div>
<p>I will assume that you&rsquo;ve cloned both your repositories into the same directory, one as <code>parent/</code>, and one as <code>sub/</code>.</p>
<pre><code>•
├── parent/
└── sub/
</code></pre>
<p>First, <strong>change to the directory of your submodule</strong> (<code>sub/</code> in my example), and execute the <code>git-rewrite-to-subfolder</code> script attached below. It&rsquo;ll lead you through the necessary steps.</p>
<p>After the rewrite is completed (which may take some time if you have many commits), <strong>change into your <code>parent/</code> repository</strong> and delete your submodule:</p>
<pre><code>$ rm -r path/to/submodule
$ vim .gitmodules
    # Here you need to remove the submodule in
    # questions from your .gitmodules file.
$ git add -A . &amp;&amp; git commit
</code></pre>
<p>Now that we&rsquo;ve deleted the submodule, we can integrate it into the repository again (still from the <code>parent/</code> directory):</p>
<pre><code>$ git remote add sub ../sub/
$ git fetch sub
$ git merge --allow-unrelated-histories -s ours --no-commit sub/master
Automatic merge went well; stopped before committing as requested
</code></pre>
<p>We&rsquo;re in the process of merging the history, but still need to add all the content from the submodule:</p>
<div class="callout warning">
  <strong>Warning:</strong> Do not clone from the submodule repository where you&rsquo;ve just rewritten the paths. This will result in wrong paths in your parent repository. Clone from your original submodule repository.
</div>
<pre><code>$ git clone git@domain.com:sub/module.git path/to/submodule
$ rm -r path/to/submodule/.git
$ git add path/to/submodule &amp;&amp; git commit
</code></pre>
<p>And you&rsquo;re done. If you take a look at any commit that happened in the submodule, you&rsquo;ll see that it now points to the correct path, and that <code>git log lib/</code> will correctly display all commits made in the submodule:</p>
<pre><code>commit e4d5e423d81540b801079b5f644edf730ca477e9
Author: Lucas
Date:   Thu Aug 15 10:35:20 2013 +0200

    Do awesome stuff in submodule

diff --git a/lib/bar.c b/lib/bar.c
index b7c5cb8..997e3bb 100644
[...]
</code></pre>
<h3 id="the-code">The code</h3>
<p>Also available as <a href="https://gist.github.com/x3ro/6242017">a gist</a>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1"># We need the TAB character for SED (Mac OS X sed does not understand \t)</span>
</span></span><span class="line"><span class="cl"><span class="nv">TAB</span><span class="o">=</span><span class="s2">&#34;</span><span class="k">$(</span><span class="nb">printf</span> <span class="s1">&#39;\t&#39;</span><span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">function</span> abort <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;</span><span class="k">$(</span>tput setaf 1<span class="k">)</span><span class="nv">$1</span><span class="k">$(</span>tput sgr0<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">function</span> request_input <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">read</span> -p <span class="s2">&#34;</span><span class="k">$(</span>tput setaf 4<span class="k">)</span><span class="nv">$1</span><span class="s2"> </span><span class="k">$(</span>tput sgr0<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">function</span> request_confirmation <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">read</span> -p <span class="s2">&#34;</span><span class="k">$(</span>tput setaf 4<span class="k">)</span><span class="nv">$1</span><span class="s2"> (y/n) </span><span class="k">$(</span>tput sgr0<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">[</span> <span class="s2">&#34;</span><span class="nv">$REPLY</span><span class="s2">&#34;</span> <span class="o">==</span> <span class="s2">&#34;y&#34;</span> <span class="o">]</span> <span class="o">||</span> abort <span class="s2">&#34;Aborted!&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cat &lt;&lt; <span class="s2">&#34;EOF&#34;</span>
</span></span><span class="line"><span class="cl">This script rewrites your entire history, moving the current repository root
</span></span><span class="line"><span class="cl">into a subdirectory. This can be useful <span class="k">if</span> you want to merge a submodule into
</span></span><span class="line"><span class="cl">its parent repository.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">For example, your main repository might contain a submodule at the path src/lib/,
</span></span><span class="line"><span class="cl">containing a file called <span class="s2">&#34;test.c&#34;</span>.
</span></span><span class="line"><span class="cl">If you would merge the submodule into the parent repository without further
</span></span><span class="line"><span class="cl">modification, all the commits to <span class="s2">&#34;test.c&#34;</span> will have the path <span class="s2">&#34;/test.c&#34;</span>, whereas
</span></span><span class="line"><span class="cl">the file now actually lives in <span class="s2">&#34;src/lib/test.c&#34;</span>.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">If you rewrite your <span class="nb">history</span> using this script, adding <span class="s2">&#34;src/lib/&#34;</span> to the path
</span></span><span class="line"><span class="cl">and the merging into the parent repository, all paths will be correct.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">NOTE: This script might <span class="nb">complete</span> garble your repository, so PLEASE apply this
</span></span><span class="line"><span class="cl">only to a clone of the repository where it does not matter <span class="k">if</span> the repo is destroyed.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">EOF
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">request_confirmation <span class="s2">&#34;Do you want to proceed?&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cat &lt;&lt; <span class="s2">&#34;EOF&#34;</span>
</span></span><span class="line"><span class="cl">Please provide the path which should be prepended to the current root. In the
</span></span><span class="line"><span class="cl">above example, that would be <span class="s2">&#34;src/lib&#34;</span>. Please note that the path MUST NOT contain
</span></span><span class="line"><span class="cl">a trailing slash.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">EOF
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">request_input <span class="s2">&#34;Please provide the desired path (e.g. &#39;src/lib&#39;):&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Escape input for SED, taken from http://stackoverflow.com/a/2705678/124257</span>
</span></span><span class="line"><span class="cl"><span class="nv">TARGET_PATH</span><span class="o">=</span><span class="k">$(</span><span class="nb">echo</span> -n <span class="s2">&#34;</span><span class="nv">$REPLY</span><span class="s2">&#34;</span> <span class="p">|</span> sed -e <span class="s1">&#39;s/[\/&amp;]/\\&amp;/g&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Last confirmation</span>
</span></span><span class="line"><span class="cl">git ls-files -s <span class="p">|</span> sed <span class="s2">&#34;s/</span><span class="si">${</span><span class="nv">TAB</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">TAB</span><span class="si">}</span><span class="nv">$TARGET_PATH</span><span class="s2">\//&#34;</span>
</span></span><span class="line"><span class="cl">request_confirmation <span class="s2">&#34;Please take a look at the printed file list. Does it look correct?&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># The actual processing happens here</span>
</span></span><span class="line"><span class="cl"><span class="nv">CMD</span><span class="o">=</span><span class="s2">&#34;git ls-files -s | sed \&#34;s/</span><span class="si">${</span><span class="nv">TAB</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">TAB</span><span class="si">}</span><span class="nv">$TARGET_PATH</span><span class="s2">\//\&#34; | GIT_INDEX_FILE=\${GIT_INDEX_FILE}.new git update-index --index-info &amp;&amp; mv \${GIT_INDEX_FILE}.new \${GIT_INDEX_FILE}&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">git filter-branch <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --index-filter <span class="s2">&#34;</span><span class="nv">$CMD</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    HEAD
</span></span></code></pre></div><br>
<div class="callout info">
    Feedback is always welcome and I try to incorporate it into the post where possible. For reasons of <a href="https://www.martinfowler.com/bliki/Datensparsamkeit.html">Datensparsamkeit</a> I do not provide a commenting solution here, however. You can reach me via email (see <a href="/">home page</a>) or <a href="http://twitter.com/fresskoma">Twitter</a>.
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
    </channel>
</rss>