Andrej’s noteshttps://blog.shadura.me/2023-04-12T15:09:46+02:00http://activitystrea.ms/schema/1.0/personAndrej Shadurahttps://shadura.me/Connecting lights to a Swytch e-bike kit2023-04-12T15:09:46+02:002023-04-12T15:09:46+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2023-04-12:/2023/04/12/swytch-e-bike-lights/<p>Last year I purchased an e-bike upgrade kit for my mother in law. We decided to install it on a bicycle she originally bought back in the 80s, which I fixed and refurbished a couple of years ago and used until September 2022 when I bought myself a Dutch Cortina …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2023/04/12/swytch-e-bike-lights/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Last year I purchased an e-bike upgrade kit for my mother in law. We decided to install it on a bicycle she originally bought back in the 80s, which I fixed and refurbished a couple of years ago and used until September 2022 when I bought myself a Dutch Cortina U4.</p>
<p>When I used this bicycle, I installed a lightweight Shutter Precision dynamo hub and compatible lights, XLC at the front, Büchel at the back. Unfortunately, since Swytch is a front wheel with a built-in electric motor, these lights don’t have a dynamo to connect to anymore, and Swytch doesn’t have a dedicated connector for lights. I tried asking the manufacturer for more documentation or schematics, but they refused to do so.</p>
<p>Luckily, a Canadian member of the Pedelecs forum managed to <a href="https://www.pedelecs.co.uk/forum/threads/should-we-bail-on-the-new-swytch-conversion-kit.43298/#post-650290">reverse-engineer the Swytch connector pinouts</a>, which gave me an idea on how to proceed. Unfortunately, that meant that I had to replace both lights, and by trial and error I found specific models that worked. Before the Axa lights, I also tried Büchel’s Tivoli e-bike light, but it didn’t work because the voltage was too low:</p>
<p><figure><img alt="Büchel Tivoli light that didn’t work" class="img-responsive" src="/images/thumbnails/posts/2023-04/büchel_thumbnail_wide.jpg" title="Büchel Tivoli light that didn’t work"/><figcaption>Büchel Tivoli light that didn’t work</figcaption></figure></p>
<p>Once I knew what to do, the rest was super easy 🙂</p>
<p>So, here we go:</p>
<ol>
<li>
<p>Get a 3-pin (yellow) <strong>female</strong> connector with a cable, e.g. <a href="https://www.aliexpress.com/item/4001091169417.html">off AliExpress</a>. Only two wires will be used, the white one is +4.2V (4-point-2, not 42!), the black one is earth. This will go into the throttle port. If you actually have a throttle, you need some sort of Y-splitter, but I don’t, so this was not an issue for me. (However, I bought both sides (M and F), just to be sure.)
<figure><img alt="Cable for the throttle port" class="img-responsive" src="/images/thumbnails/posts/2023-04/swytch-3pin-cable-ali_thumbnail_wide.jpg" title="Cable for the throttle port"/><figcaption>Cable for the throttle port</figcaption></figure></p>
</li>
<li>
<p>Purchase an <a href="https://www.axasecurity.com/bike-security/en-gb/products/lights/7/92915396SC/axa-606-e6-48">Axa 606 E6-48 front light</a>. The 606 comes in two versions, for dynamos and e-bikes, use the one for e-bikes; despite being officially rated as 6—48V, these lights work quite well off 4.2V too.
<figure><img alt="Axa 606 E6-48 light" class="img-responsive" src="/images/thumbnails/posts/2023-04/axa-606-light_thumbnail_wide.jpg" title="Axa 606 E6-48 light"/><figcaption>Axa 606 E6-48 light</figcaption></figure></p>
</li>
<li>
<p>Purchase an <a href="https://www.axasecurity.com/bike-security/en-gb/products/lights/7/93954895SC/axa-spark-steady-50-80mm">Axa Spark Steady rear light</a>. This light works with both AC and DC (just like the 606, the official rating is 6—48V), and works off 4.2V without an issue.
<figure><img alt="Axa Spark light" class="img-responsive" src="/images/thumbnails/posts/2023-04/axa-spark_thumbnail_wide.jpg" title="Axa Spark light"/><figcaption>Axa Spark light</figcaption></figure></p>
</li>
<li>
<p>Wire lights up. I used tiny wire terminals to join the wires, but I’m sure there are better options too. Insulate them well, make sure the red wire from the throttle connector is insulated too. I used a bunch of shrink tubes and black insulation tape. Since the voltage is not wildly different from what the dynamo hub produced (although AC, not DC), I was able to reuse the cable I had already routed to the rear carrier.</p>
</li>
<li>
<p>Lights go on automatically as soon as you touch the power button on the battery pack, and stay on until the battery pack is switched off completely. I was considering adding a handlebar switch, but since I lost the only one I had, I had to do without.</p>
</li>
</ol>
<p><figure><img alt="Front light" class="img-responsive" src="/images/thumbnails/posts/2023-04/favorit-front_thumbnail_wide.jpg" title="Front light"/><figcaption>Front light</figcaption></figure>
<figure><img alt="Rear light" class="img-responsive" src="/images/thumbnails/posts/2023-04/favorit-rear_thumbnail_wide.jpg" title="Rear light"/><figcaption>Rear light</figcaption></figure></p>
<p>The side effect of using the Axa Spark at the rear is that it has a capacitor inside and keeps going for a couple more minutes after the battery pack is off — I haven’t decided whether that’s a benefit or a drawback 😄</p>
<p><strong>This post has been amended on 2023-08-18.</strong> Previously, it incorrectly stated a cable with a male connector is necessary. However, it is the cable leading from Swytch that is male, and the matching part connecting to the lights has to be female.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleTo England by train (part 2)2022-04-23T08:45:25+02:002022-04-23T08:45:25+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2022-04-23:/2022/04/23/england-by-train-part-2/<p>My <a href="https://blog.shadura.me/2021/08/10/england-by-train-part-1/">attempt to travel to the UK by train last year</a> didn’t go quite as well as I expected. As I mentioned in that blog post, the NightJet to Brussels was cancelled, forcing me to fly instead. This disappointed me so much that I actually unpublished the blog post …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2022/04/23/england-by-train-part-2/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>My <a href="https://blog.shadura.me/2021/08/10/england-by-train-part-1/">attempt to travel to the UK by train last year</a> didn’t go quite as well as I expected. As I mentioned in that blog post, the NightJet to Brussels was cancelled, forcing me to fly instead. This disappointed me so much that I actually unpublished the blog post minutes after it was originally put online. The timing was nearly perfect: I type <code>make publish</code> and I get an email from ÖBB saying they don’t know if my train is going to run. Of course it didn’t, as Deutsche Bahn workers went ahead with their strike. The blog post sat in the drafts for more than half a year until yesterday, when I finally updated and published it.</p>
<p>The reason I have finally published it is that I’m going to the UK by train once again. Now, unless railways decide to hold a strike again, fully by train both ways. Very expensive, especially compared to the price of Ryanair flights to my destination. Unfortunately, even though Eurostar added more daily services, they’re still not cheap, especially on a shorter notice. This seems to apply to the ÖBB’s NightJet even more: I tried many routes between Vienna and London, and the cheapest still seemed to be the connection through Brussels.</p>
<p>While researching the prices of the tickets, it seems all booking systems decided to stop co-operating. The Trainline refused to let me look up any trains at all, even with all tracking and advertisement allowed, SNCF kepts showing me overly generic errors (<em>Sorry, an error has occurred.</em>), while the GWR booking system kept crashing with a <em>500 Internal Server Error</em> for about two hours.</p>
<p><figure><img alt="Error messages at the websites of Trainline, GWR and SNCF" class="img-responsive" src="/images/posts/2022-04/error-error-error.jpeg" title="Trainline, GWR and SNCF kept crashing"/><figcaption>Trainline, GWR and SNCF kept crashing</figcaption></figure></p>
<p>Eventually, having spent a lot of time and money, I’ve booked my trains to, within and back from England. This time, Cambridge is among the destinations.</p>
<figure>
<img alt="The map of the train route from Bratislava to Cambridge through Brussels and London" class="img-responsive" src="/images/posts/2022-04/train-bratislava-cambridge.jpeg" srcset="/images/posts/2022-04/train-bratislava-cambridge-1326.jpeg 1326w,
/images/posts/2022-04/train-bratislava-cambridge-800.jpeg 800w,
/images/posts/2022-04/train-bratislava-cambridge-697.jpeg 697w,
/images/posts/2022-04/train-bratislava-cambridge.jpeg" title="The complete route"/>
<figcaption>The complete route</figcaption>
</figure>
<table class="table table-striped">
<thead>
<tr>
<th>Date</th>
<th>Station</th>
<th>Arrival</th>
<th>Departure</th>
<th>Train</th>
</tr>
</thead>
<tbody>
<tr>
<td>26.4</td>
<td>Bratislava hl.st.</td>
<td></td>
<td>18:37</td>
<td>REX 2529</td>
</tr>
<tr>
<td></td>
<td>Wien Hbf</td>
<td>19:44</td>
<td>20:13</td>
<td>NJ 40490</td>
</tr>
<tr>
<td>27.4</td>
<td>Bruxelles-Midi</td>
<td>9:54</td>
<td>15:56</td>
<td>EST 9145</td>
</tr>
<tr>
<td></td>
<td>London St Pancras</td>
<td>17:01</td>
<td>17:43</td>
<td>ThamesLink</td>
</tr>
<tr>
<td></td>
<td>Cambridge</td>
<td>18:43</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>I’m not sure about it yet, but I may end up taking an earlier train from Bratislava just to ensure there’s enough time for the change in Vienna; similarly, I’m not sure how much time I will be spending at St Pancras, so I may take one of the later trains.</p>
<p>P.S. The maps in this and other posts were created using <a href="http://umap.openstreetmap.fr/en/">uMap</a>; the map data come from <a href="https://openstreetmap.org/">OpenStreetMap</a>. The train route visualisation was generated with help of <a href="https://signal.eu.org/osm/">signal.eu.org</a>.</p>
<p><a href="https://brid.gy/publish/twitter" style="display: none;"></a>
<a href="https://brid.gy/publish/mastodon" style="display: none;"></a>
<a href="https://fed.brid.gy/" style="display: none;"></a></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleCoffee gear upgrade2021-12-12T12:49:30+01:002021-12-12T12:49:30+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2021-12-12:/2021/12/12/coffee-gear-upgrade/<p>Two weeks ago I decided to make myself a combined birthday and Christmas present and upgrade my coffee gear.</p>
<p>I’ve got my first espresso machine back in 2013, it was a cheap Saeco Philips Poemia, which made reasonably
drinkable coffee, but not being able to make good coffee made …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2021/12/12/coffee-gear-upgrade/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Two weeks ago I decided to make myself a combined birthday and Christmas present and upgrade my coffee gear.</p>
<p>I’ve got my first espresso machine back in 2013, it was a cheap Saeco Philips Poemia, which made reasonably
drinkable coffee, but not being able to make good coffee made me increasingly unhappy about it. However,
since it worked, I wasn’t motivated enough to change anything — until it stopped working. One day the nut holding
the ‘shower screen’ broke, and I couldn’t replace it.</p>
<p>Having no coffee machine is arguably worse than having a mediocre one, so I started looking for a new one in the budget
range. Having spent about two months reading reviews for all sorts of manual espresso machines, I realised the best
thing I can probably do for the money I was willing to spend at the time was to buy a second-hand Gaggia Classic.
Which is what I did: I paid €260 to a person who apparently decided they prefer to press a button to get their espresso
rather than have to prepare it themselves.</p>
<p>My first attempts at making espresso weren’t very much successful, as my hand grinder couldn’t produce the right grind for
espresso (without using pressurised baskets), so I quickly upgraded it to the €50 De’Longhi electric grinder, which was much
better for espresso.</p>
<p><figure><img alt="Gaggia Classic 2015 and De’Longhi grinder" class="img-responsive" src="/images/posts/2021-12/gaggia-2015-and-delonghi-grinder.jpg" title="Gaggia Classic 2015 and De’Longhi grinder"/><figcaption>Gaggia Classic 2015 and De’Longhi grinder</figcaption></figure></p>
<p>This setup has worked for me for nearly 4 years, but over the time the Gaggia started malfunctioning.</p>
<p>See, this particular Gaggia Classic is the 2015 model, which resulted in the overhaul of the design after Gaggia was acquired by
Philips. They replaced the boiler, changed the exterior design a bit, and — importantly for me — replaced the fully metal group
head with the metal and plastic version typically found in cheap espresso machines like my old Poemia.</p>
<p><figure><img alt="The Gaggia Classic 2015 group head" class="img-responsive" src="/images/posts/2021-12/cheapo-portafilter-holder.jpg" title="The Gaggia Classic 2015 group head"/><figcaption>The Gaggia Classic 2015 group head</figcaption></figure></p>
<p>The trouble with this one is that the plastic bit (barely seen on the picture, but it’s inserted into the notches on the sides
of the group head) is that it gets damaged over the time, especially when the portafilter is inserted very tightly. The more
damaged it gets, the tigher it is necessary to insert the portafilter to avoid leakage, the more damaged it gets and so on.</p>
<p>At one point, the Gaggia was leaking water every time I was making coffee, affecting the quality of the brew and making a mess
in the kitchen. I made a mistake and removed the plastic bit only to realise it cannot be purchased separately and nobody knows
how to put it back once it’s been removed; I ended up paying more than a hundred euro to replace the group head as a whole.</p>
<p>Once I’ve got the Gaggia back, I became too conscious of the potential damage I can make by overengaging the portafilter, I decided
it’s probably the time to get a new coffee machine.</p>
<p><figure><img alt="Gaggia Classic 2015 vs 2019" class="img-responsive" src="/images/posts/2021-12/gaggia-2015-vs-2019.jpg" title="Gaggia Classic 2015 vs 2019"/><figcaption>Gaggia Classic 2015 vs 2019</figcaption></figure></p>
<p>The makers of Gaggia listened to the critics and undid the 2015 changes to the Gaggia Classic design, reverting to the previous one
and fixing it — they basically ‘merged’ the fixes many of the owners of the old Gaggia did themselves. The group head is now without
any plastic, so I don’t have to worry that much about damaging it accidentally.</p>
<p>A friend pointed out that my grinder is probably not good enough and recommended a couple of models to me; I checked
<a href="https://coffeeblog.co.uk/best-budget-electric-burr-coffee-grinders-in-the-uk/">Kev’s Coffee Blog</a> and found a grinder, Sage Dose Control Pro,
which was available on sale in my local shop for a reasonable price.</p>
<p>I’ve also got a portafilter holder to make tamping more comfortable — I used to tamp against an edge of the sink:
<figure><img class="img-responsive" src="/images/posts/2021-12/tamping-against-sink.jpg"/></figure></p>
<p>The final setup:
<figure><img alt="Gaggia Classic 2019 and Sage BCG600 Dose Control Pro" class="img-responsive" src="/images/posts/2021-12/gaggia-2019-and-sage-grinder.jpg" title="Gaggia Classic 2019 and Sage BCG600 Dose Control Pro"/><figcaption>Gaggia Classic 2019 and Sage BCG600 Dose Control Pro</figcaption></figure></p>
<p>What I learnt from this is that the grinder does indeed make a huge difference. I am now able to consistently produce brews I would only occasionally
get with the old De’Longhi grinder. There is one downside to the new grinder.</p>
<p><img alt="Grinder review at Alza.sk" src="/images/posts/2021-12/sage-grinder-review.png"/></p>
<p>Happy with my new purchase, I went to read this review and thought to myself: ‘lucky me, my grinder is absolutely quiet!’ And then I realised that
the noise in my kitchen is not, in fact, produced by the fridge, but the grinder. Well, a cheap switched plug solved the issue completely (I wish
sockets here each had a switch like they usually do in the UK!)</p>
<p><img alt="Switched plug" src="/images/posts/2021-12/switched-plug.jpg"/></p>
<p><a href="https://brid.gy/publish/twitter" style="display: none;"></a>
<a href="https://brid.gy/publish/mastodon" style="display: none;"></a></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleTo England by train (part 1)2021-08-10T16:34:54+02:002022-04-22T15:25:39+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2021-08-10:/2021/08/10/england-by-train-part-1/<p><em>This post was written in August 2021. Just as I was going to publish it, I received an email from ÖBB stating that due to a railway strike in Germany my night train would be cancelled. Since the rest of the trip has already been booked well in advance, I …</em><footer><a rel="full-article" class="read-more btn btn-primary" href="/2021/08/10/england-by-train-part-1/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p><em>This post was written in August 2021. Just as I was going to publish it, I received an email from ÖBB stating that due to a railway strike in Germany my night train would be cancelled. Since the rest of the trip has already been booked well in advance, I had to take a plane to Charleroi and a bus to Brussels to catch my Eurostar. Ultimately, I ended up publishing it in April 2022, just as I’m about to leave for a fully train-powered trip to the UK once again.</em></p>
<p>Before the pandemic started, I planned to use the last months of my then-expiring UK visa and go to England by train. I’ve completed two train long journeys by that time already, to <a href="/2020/02/21/fosdem-by-train-followup/">Brussels</a> and to Belarus and Ukraine, but this would be something quite different, as I wanted to have multiple stops on my way, use night trains where it made sense, and to go through the Channel Tunnel.</p>
<p>The Channel Tunnel fascinated me since my childhood; I first read about it in the Soviet <em>Science and Life</em> magazine (<em>Наука и жизнь</em>) when I was seven. I’ve never had the chance to use it though, since to board any train going though it I’d first need to get to France, Belgium or the Netherlands, making it significantly more expensive than the cheap €30 Ryanair flights to Stansted.</p>
<p>As the coronavirus spread across the world, all of my travel plans along with plans for a sabbatical had to be cancelled. During 2020, I only managed to go on two weekend trips to Prague and Budapest, followed by a two-weeks holiday on Crete (we returned just a couple of weeks before the infection numbers rose and lockdowns started). I do realise that a lot of people couldn’t even have this much because the situation in their countries was much worse — we were lucky to have had at least some travel.</p>
<p>Fast forward to August 2021, I’m fully vaccinated, I — once again — have a UK visa for five years, and the UK finally recognises the EU vaccination passports — yay! I can finally go to Devon to see my mother and sister again. By train, of course.</p>
<p>Compared to my original plan, this journey will be different: about the same or even more expensive than I originally planned, but shorter and with fewer stops on the way. My original plan would be to take multiple trains from Bratislava to France or Belgium and complete this segment of the trip in about three days, enjoying my stay in a couple of cities on the way. Instead, I’m taking a direct NightJet from Vienna to Brussels, not stopping anywhere on the way.</p>
<p><figure><img alt="Map: train route from Bratislava to Brussels" class="img-responsive" src="/images/posts/2021-08/train-bratislava-brussels.png" title="Train route from Bratislava to Brussels"/><figcaption>Train route from Bratislava to Brussels</figcaption></figure></p>
<p>Since I was booking my trip just two weeks ahead, the price of the ticket is not that I hoped for, but much higher: €109 for the ticket itself and €60 for the berth (advance bookings could be about twice as cheap).</p>
<p>Next, to London! Eurostar is still on a very much reduced schedule, running one train only from Amsterdam through Brussels and Lille to London each day. This means, of course, higher ticket prices (I paid about €100 for the ticket) and longer waiting time in Brussels — my sleeper arrives about 10 am, but the Eurostar train is scheduled to depart at 3 pm.</p>
<p><figure><img alt="Map: train route from Brussels to London" class="img-responsive" src="/images/posts/2021-08/train-brussels-london.png" title="Train route from Brussels to London"/><figcaption>Train route from Brussels to London</figcaption></figure></p>
<p>The train makes a stop in Lille, which I initially suspected to be risky as at the time when I booked my tickets, as at the time France was on the <em>amber plus</em> list for the UK, requiring a quarantine upon arrival. However, <a href="https://www.telegraph.co.uk/news/2021/07/17/eurostar-passengers-travelling-france-segregated/">Eurostar announced</a> that they will assign travellers from Lille to a different carriage to avoid other passengers having to go to quarantine, but recently France was <a href="https://www.gov.uk/guidance/red-amber-and-green-list-rules-for-entering-england#amber-list">taken off the <em>amber plus</em> list</a>.</p>
<p>The train fare system in the UK is something I don’t quite understand, as sometimes split tickets are cheaper, sometimes they’re expensive, sometimes prices for the same service at different times can be vastly different, <em>off-peak</em> tickets don’t say what exactly <em>off-peak</em> means (very few people in the UK are asked were able to tell me when exactly <em>off-peak</em> hours are). Curiously, transfers between train stations using London Underground services can be included into railway tickets, but some last mile connection like Exeter to Honiton cannot (but this used to be possible). Both <a href="https://www.gwr.com/">GWR.com</a> and TrainLine refused to sell me a single ticket from London to Honiton through Exeter, insisting I split the ticket at Exeter St Davids or take the slower South Western train to Honiton via Salisbury and Yeovil. I ended up buying a £57 ticket from Paddington to Exeter St Davids with the first segment being the London Underground from St Pancras, and a separate £7.70 ticket to Honiton.</p>
<p><figure><img alt="Map: arrival at St Pancras, the underground, departure from Paddington" class="img-responsive" src="/images/posts/2021-08/change-in-london.png" title="Change of trains in London"/><figcaption>Change of trains in London</figcaption></figure>
<figure><img alt="Map: arrival at Exeter St Davids, change to a South Western train, arrival at Honiton" class="img-responsive" src="/images/posts/2021-08/change-in-exeter.png" title="Change of trains in Exeter"/><figcaption>Change of trains in Exeter</figcaption></figure></p>
<table class="table table-striped">
<thead>
<tr>
<th>Date</th>
<th>Station</th>
<th>Arrival</th>
<th>Departure</th>
<th>Train</th>
</tr>
</thead>
<tbody>
<tr>
<td>12.8</td>
<td>Bratislava-Petržalka</td>
<td></td>
<td>18:15</td>
<td>REX 7756</td>
</tr>
<tr>
<td></td>
<td>Wien Hbf</td>
<td>19:15</td>
<td>19:53</td>
<td>NJ 50490</td>
</tr>
<tr>
<td>13.8</td>
<td>Bruxelles-Midi</td>
<td>9:55</td>
<td>15:06</td>
<td>EST 9145</td>
</tr>
<tr>
<td></td>
<td>London St Pancras</td>
<td>16:03</td>
<td>16:34</td>
<td>TfL</td>
</tr>
<tr>
<td></td>
<td>London Paddington</td>
<td>16:49</td>
<td>17:04</td>
<td>GWR 59231</td>
</tr>
<tr>
<td></td>
<td>Exeter St Davids</td>
<td>19:19</td>
<td>19:25</td>
<td>SWR 52706</td>
</tr>
<tr>
<td></td>
<td>Honiton</td>
<td>19:54</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>Unfortunately, due to the price of the tickets, I’m taking a £15 Ryanair flight back 🙂</p>
<h3>Update after the journey</h3>
<p>Since I flew to Charleroi instead of comfortably sleeping in a night train, I had to put up with inconveniences of airports, including cumbersome connections to the nearby cities. The only reasonable way of getting from Charleroi to Brussels is an overcrowded bus which takes almost an hour to arrive. I used to take this bus when I tried to save money on my way to FOSDEM, and I must admit it’s not something I missed.</p>
<p>Boarding the Eurostar train went fine, my vaccination passport and Covid test wasn’t really checked, just glanced at. The waiting room was a bit of a disappointment, with bars closed and vending machines broken. Since it was underground, I couldn’t even see the trains until the very last moment when we were finally allowed on the platform. The train itself, while comfortable, disappointed me with the bistro carriage: standing only, instant coffee, poor selection of food and drinks. I’m glad I bought some food at Carrefour at the Midi station!</p>
<p>When I arrived in Exeter, I soon found out why the system refused to sell me a through ticket: 6 minutes is not enough to change trains at Exeter St Davids! Or, it might have been if I took the right footbridge — but I took the one which led into a very talkative (and slow!) lift. I ended up running to the train just as it closed the doors and departed, leaving me tin Exeter for an hour until. I used this chance and walked to Exeter Central, and had a pint in a conveniently located pub around the corner.</p>
<p>P.S. The maps in this and other posts were created using <a href="http://umap.openstreetmap.fr/en/">uMap</a>; the map data come from <a href="https://openstreetmap.org/">OpenStreetMap</a>. The train route visualisation was generated with help of the <a href="http://raildar.fr">Raildar.fr</a> OSRM instance.</p>
<p><a href="https://brid.gy/publish/twitter" style="display: none;"></a>
<a href="https://brid.gy/publish/mastodon" style="display: none;"></a>
<a href="https://fed.brid.gy/" style="display: none;"></a></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleTransitioning to a new OpenPGP key2021-01-01T16:08:45+01:002021-01-01T16:08:45+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2021-01-01:/2021/01/01/new-openpgp-key/<p>Following <span class="h-card"><a class="u-url mention" href="https://dkg.fifthhorseman.net/blog/author/daniel-kahn-gillmor.html">dkg</a></span>’s <a href="https://dkg.fifthhorseman.net/blog/2021-dkg-openpgp-transition.html">example</a>, I decided to finally transition to my new <code>ed25519</code>/<code>cv25519</code> key.</p>
<p>Unlike Daniel, I’m not yet trying to split identities, but I’m using this chance to drop old identities I no longer use. My new key only has my main email address and the …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2021/01/01/new-openpgp-key/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Following <span class="h-card"><a class="u-url mention" href="https://dkg.fifthhorseman.net/blog/author/daniel-kahn-gillmor.html">dkg</a></span>’s <a href="https://dkg.fifthhorseman.net/blog/2021-dkg-openpgp-transition.html">example</a>, I decided to finally transition to my new <code>ed25519</code>/<code>cv25519</code> key.</p>
<p>Unlike Daniel, I’m not yet trying to split identities, but I’m using this chance to drop old identities I no longer use. My new key only has my main email address and the Debian one, and only those versions of my name I still want around.</p>
<p>My old PGP key (at the moment in the Debian keyring) is:</p>
<div class="highlight"><pre><span></span><code><span class="n">pub</span><span class="w"> </span><span class="n">rsa4096</span><span class="o">/</span><span class="mh">0x6EA4D2311A2D268D</span><span class="w"> </span><span class="mi">2010</span><span class="o">-</span><span class="mi">10</span><span class="o">-</span><span class="mi">13</span><span class="w"> </span><span class="o">[</span><span class="n">SC</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">expires: 2021-11-11</span><span class="o">]</span>
<span class="w"> </span><span class="mi">782130</span><span class="n">B4C9944247977B82FD6EA4D2311A2D268D</span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrej</span><span class="w"> </span><span class="n">Shadura</span><span class="w"> </span><span class="o"><</span><span class="n">andrew</span><span class="nv">@shadura</span><span class="p">.</span><span class="n">me</span><span class="o">></span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrew</span><span class="w"> </span><span class="n">Shadura</span><span class="w"> </span><span class="o"><</span><span class="n">andrew</span><span class="nv">@shadura</span><span class="p">.</span><span class="n">me</span><span class="o">></span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrew</span><span class="w"> </span><span class="n">Shadura</span><span class="w"> </span><span class="o"><</span><span class="n">andrewsh</span><span class="nv">@debian</span><span class="p">.</span><span class="n">org</span><span class="o">></span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrew</span><span class="w"> </span><span class="n">O</span><span class="p">.</span><span class="w"> </span><span class="n">Shadoura</span><span class="w"> </span><span class="o"><</span><span class="n">Andrew</span><span class="p">.</span><span class="n">Shadoura</span><span class="nv">@gmail</span><span class="p">.</span><span class="n">com</span><span class="o">></span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrej</span><span class="w"> </span><span class="n">Shadura</span><span class="w"> </span><span class="o"><</span><span class="n">andrewsh</span><span class="nv">@debian</span><span class="p">.</span><span class="n">org</span><span class="o">></span>
<span class="n">sub</span><span class="w"> </span><span class="n">rsa4096</span><span class="o">/</span><span class="mh">0xB2C0FE967C940749</span><span class="w"> </span><span class="mi">2010</span><span class="o">-</span><span class="mi">10</span><span class="o">-</span><span class="mi">13</span><span class="w"> </span><span class="o">[</span><span class="n">E</span><span class="o">]</span>
<span class="n">sub</span><span class="w"> </span><span class="n">rsa3072</span><span class="o">/</span><span class="mh">0xC8C5F253DD61FECD</span><span class="w"> </span><span class="mi">2018</span><span class="o">-</span><span class="mi">03</span><span class="o">-</span><span class="mi">02</span><span class="w"> </span><span class="o">[</span><span class="n">S</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">expires: 2021-11-11</span><span class="o">]</span>
<span class="n">sub</span><span class="w"> </span><span class="n">rsa2048</span><span class="o">/</span><span class="mh">0x5E408CD91CD839D2</span><span class="w"> </span><span class="mi">2018</span><span class="o">-</span><span class="mi">03</span><span class="o">-</span><span class="mi">10</span><span class="w"> </span><span class="o">[</span><span class="n">S</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">expires: 2021-11-11</span><span class="o">]</span>
</code></pre></div>
<p>The is the key I’ve been using in Debian from the very beginning, and its copies at the SKS keyserver network still have my first DD signature from <span class="h-card"><a class="u-url mention" href="https://mastodon.social/@angdraug">angdraug</a></span>:</p>
<div class="highlight"><pre><span></span><code><span class="n">sig</span><span class="w"> </span><span class="n">sig</span><span class="w"> </span><span class="mi">85</span><span class="n">EE3E0E</span><span class="w"> </span><span class="mi">2010</span><span class="o">-</span><span class="mi">12</span><span class="o">-</span><span class="mi">03</span><span class="w"> </span><span class="n">__________</span><span class="w"> </span><span class="n">__________</span><span class="w"> </span><span class="n">Dmitry</span><span class="w"> </span><span class="n">Borodaenko</span><span class="w"> </span><span class="o"><</span><span class="n">angdraug</span><span class="nv">@mail</span><span class="p">.</span><span class="n">ru</span><span class="o">></span>
<span class="n">sig</span><span class="w"> </span><span class="n">sig</span><span class="w"> </span><span class="n">CB4D38A9</span><span class="w"> </span><span class="mi">2010</span><span class="o">-</span><span class="mi">12</span><span class="o">-</span><span class="mi">03</span><span class="w"> </span><span class="n">__________</span><span class="w"> </span><span class="n">__________</span><span class="w"> </span><span class="n">Dmitry</span><span class="w"> </span><span class="n">Borodaenko</span><span class="w"> </span><span class="o"><</span><span class="n">angdraug</span><span class="nv">@debian</span><span class="p">.</span><span class="n">org</span><span class="o">></span>
</code></pre></div>
<p>My new PGP key is:</p>
<div class="highlight"><pre><span></span><code><span class="n">pub</span><span class="w"> </span><span class="n">ed25519</span><span class="o">/</span><span class="mh">0xE8446B4AC8C77261</span><span class="w"> </span><span class="mi">2016</span><span class="o">-</span><span class="mi">06</span><span class="o">-</span><span class="mi">13</span><span class="w"> </span><span class="o">[</span><span class="n">SC</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">expires: 2022-06-25</span><span class="o">]</span>
<span class="w"> </span><span class="mi">83</span><span class="n">DCD17F44B22CC83656EDA1E8446B4AC8C77261</span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrej</span><span class="w"> </span><span class="n">Shadura</span><span class="w"> </span><span class="o"><</span><span class="n">andrew</span><span class="nv">@shadura</span><span class="p">.</span><span class="n">me</span><span class="o">></span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrew</span><span class="w"> </span><span class="n">Shadura</span><span class="w"> </span><span class="o"><</span><span class="n">andrew</span><span class="nv">@shadura</span><span class="p">.</span><span class="n">me</span><span class="o">></span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrej</span><span class="w"> </span><span class="n">Shadura</span><span class="w"> </span><span class="o"><</span><span class="n">andrewsh</span><span class="nv">@debian</span><span class="p">.</span><span class="n">org</span><span class="o">></span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrew</span><span class="w"> </span><span class="n">Shadura</span><span class="w"> </span><span class="o"><</span><span class="n">andrewsh</span><span class="nv">@debian</span><span class="p">.</span><span class="n">org</span><span class="o">></span>
<span class="n">uid</span><span class="w"> </span><span class="o">[</span><span class="n">ultimate</span><span class="o">]</span><span class="w"> </span><span class="n">Andrei</span><span class="w"> </span><span class="n">Shadura</span><span class="w"> </span><span class="o"><</span><span class="n">andrew</span><span class="nv">@shadura</span><span class="p">.</span><span class="n">me</span><span class="o">></span>
<span class="n">sub</span><span class="w"> </span><span class="n">cv25519</span><span class="o">/</span><span class="mh">0xD5A55606B6539A87</span><span class="w"> </span><span class="mi">2016</span><span class="o">-</span><span class="mi">06</span><span class="o">-</span><span class="mi">13</span><span class="w"> </span><span class="o">[</span><span class="n">E</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">expires: 2022-06-25</span><span class="o">]</span>
<span class="n">sub</span><span class="w"> </span><span class="n">ed25519</span><span class="o">/</span><span class="mh">0x52E0EA6F91F1DB8A</span><span class="w"> </span><span class="mi">2016</span><span class="o">-</span><span class="mi">06</span><span class="o">-</span><span class="mi">13</span><span class="w"> </span><span class="o">[</span><span class="n">A</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">expires: 2022-06-25</span><span class="o">]</span>
</code></pre></div>
<p>If you signed my old key and are reading this, please consider signing my new key; if you feel you need to re-confirm this, feel free to contact me; otherwise, a copy of this statement signed by both the old and new keys is available <a href="https://blog.shadura.me/2021/01/01/new-openpgp-key/2021-01-01-new-openpgp-key.txt">here</a>.</p>
<p>I have uploaded this new key to <a href="https://keys.openpgp.org">keys.openpgp.org</a>, and also published it through WKD and the SKS network. Both keys can also be downloaded from <a href="https://shadura.me/key.pgp">my website</a>.</p>
<p><a href="https://brid.gy/publish/twitter" style="display: none;"></a>
<a href="https://brid.gy/publish/mastodon" style="display: none;"></a>
<a href="https://fed.brid.gy/" style="display: none;"></a></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleMaking the blog part of the Fediverse and IndieWeb2020-12-30T20:07:03+01:002020-12-30T20:07:03+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2020-12-30:/2020/12/30/blog-on-the-fediverse/<p>I’ve just made my blog available on the Fediverse, at least partially.</p>
<p>Yesterday while browsing Hacker News, I saw <a href="https://carlschwan.eu/">Carl Schwan</a>’s post <a href="https://carlschwan.eu/2020/12/29/adding-comments-to-your-static-blog-with-mastodon/">Adding comments to your static blog with Mastodon</a><sup>(<a href="https://linuxrocks.online/@carl/105463655803971969">m</a>)</sup> about him replacing Disqus with replies posted at Mastodon. Just on Monday I was thinking, why can …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2020/12/30/blog-on-the-fediverse/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>I’ve just made my blog available on the Fediverse, at least partially.</p>
<p>Yesterday while browsing Hacker News, I saw <a href="https://carlschwan.eu/">Carl Schwan</a>’s post <a href="https://carlschwan.eu/2020/12/29/adding-comments-to-your-static-blog-with-mastodon/">Adding comments to your static blog with Mastodon</a><sup>(<a href="https://linuxrocks.online/@carl/105463655803971969">m</a>)</sup> about him replacing Disqus with replies posted at Mastodon. Just on Monday I was thinking, why can’t blogs participate in Fediverse? I tried to use WriteFreely as a replacement for Pelican, only to find it very limited, so I thought I might write a gateway to expose the Atom feed using ActivityPub. Turns out, someone already did that: <a href="https://brid.gy/">Bridgy</a>, a service connecting websites to Twitter, Mastodon and other social media, also has a Fediverse counterpart, <a href="https://fed.brid.gy/">Fed.brid.gy</a> — just what I was looking for!</p>
<p>I won’t go deeply into the details, but just outline issues I had to deal with:</p>
<ul>
<li>Bridgy relies on microformats. While I had some microformats and Schema.org microdata already at both blog and the homepage, they were not sufficiently good for Bridgy to use.</li>
<li>Webmention: I had to set up <a href="https://webmention.io">https://webmention.io</a> to act as Webmention host for me.</li>
<li>I ran into an <a href="https://github.com/snarfed/bridgy-fed/issues/73">issue</a> with Mastodon being more picky about signatures — which the author <span class="h-card"><a class="u-url mention" href="https://snarfed.org/">Ryan Barrett</a></span> promptly fixed.</li>
</ul>
<p>The end result is not fully working yet, since posts don’t appear yet, but I can be found and followed as <code>@shadura.me@shadura.me</code>.</p>
<p>As a bonus I enabled <a href="https://indieauth.com/">IndieAuth</a> at my website, so I can log into compatible services with just the URL of my website.</p>
<p><a href="https://brid.gy/publish/twitter" style="display: none;"></a>
<a href="https://brid.gy/publish/mastodon" style="display: none;"></a></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleVendoring Rust dependencies for a Debian derivative2020-12-22T19:26:57+01:002020-12-22T19:26:57+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2020-12-22:/2020/12/22/vendoring-rust-in-debian-derivative/<p>Recently, I needed to package a <a href="https://crates.io/crates/libslirp">Rust crate <code>libslirp</code></a> for a <a href="https://www.apertis.org/">Apertis, a Debian derivative</a>. <code>libslirp</code> is used by the newly release UML backend of <a href="https://github.com/go-debos/debos">debos</a>, our Debian image build tool. Unfortunately, this crate hasn’t yet been properly packaged for Debian proper, so I could not simply pull the …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2020/12/22/vendoring-rust-in-debian-derivative/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Recently, I needed to package a <a href="https://crates.io/crates/libslirp">Rust crate <code>libslirp</code></a> for a <a href="https://www.apertis.org/">Apertis, a Debian derivative</a>. <code>libslirp</code> is used by the newly release UML backend of <a href="https://github.com/go-debos/debos">debos</a>, our Debian image build tool. Unfortunately, this crate hasn’t yet been properly packaged for Debian proper, so I could not simply pull the packaging from Debian. Even worse, its build dependencies haven’t all been packaged yet. Most importantly, I have only uploaded <a href="https://crates.io/crates/libslirp">zbus</a> to Debian today, and at that time none of its dependencies were in Debian either.</p>
<p>Another issue with this were that each crate is packaged for Debian as a separate package, making the process a bit more tricky since I’d need to import all of the crates into Apertis separately. Doing that takes time and is further complicated by the CI loop we’re using which requires the full build process to complete for a package before a pipeline a dependent package can run.</p>
<p>Having all that considered, I took a shortcut: I vendored all the build dependencies with the package itself, and here’s how.</p>
<p>I started with <a href="https://salsa.debian.org/rust-team/debcargo-conf">debcargo-conf</a>, where the not-yet-complete packaging lives. With <code>debcargo</code>, I generated the source package as if I were to upload to Debian. Since I’ll be vendoring the dependencies, I have removed most of the Rust dependencies and replaced them with those extra dependencies needed by those crates.
So, I replaced this:</p>
<div class="highlight"><pre><span></span><code><span class="n">Build</span><span class="o">-</span><span class="n">Depends</span><span class="p">:</span><span class="w"> </span><span class="n">debhelper</span><span class="w"> </span><span class="p">(</span><span class="o">>=</span><span class="w"> </span><span class="mi">12</span><span class="p">),</span>
<span class="w"> </span><span class="n">dh</span><span class="o">-</span><span class="n">cargo</span><span class="w"> </span><span class="p">(</span><span class="o">>=</span><span class="w"> </span><span class="mi">24</span><span class="p">),</span>
<span class="w"> </span><span class="n">cargo</span><span class="p">:</span><span class="n">native</span><span class="p">,</span>
<span class="w"> </span><span class="n">rustc</span><span class="p">:</span><span class="n">native</span><span class="p">,</span>
<span class="w"> </span><span class="n">libstd</span><span class="o">-</span><span class="n">rust</span><span class="o">-</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">enumflags2</span><span class="o">-</span><span class="mf">0.6</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="w"> </span><span class="p">(</span><span class="o">>=</span><span class="w"> </span><span class="mf">0.6</span><span class="o">.</span><span class="mi">4</span><span class="o">-~~</span><span class="p">),</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">ipnetwork</span><span class="o">-</span><span class="mf">0.17</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">lazy</span><span class="o">-</span><span class="k">static</span><span class="o">-</span><span class="mi">1</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="w"> </span><span class="p">(</span><span class="o">>=</span><span class="w"> </span><span class="mf">1.4</span><span class="o">-~~</span><span class="p">),</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">libc</span><span class="o">-</span><span class="mf">0.2</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">libslirp</span><span class="o">-</span><span class="n">sys</span><span class="o">-</span><span class="mi">4</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="w"> </span><span class="p">(</span><span class="o">>=</span><span class="w"> </span><span class="mf">4.2</span><span class="o">.</span><span class="mi">0</span><span class="o">-~~</span><span class="p">),</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">libsystemd</span><span class="o">-</span><span class="mf">0.2</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">mio</span><span class="o">-</span><span class="mf">0.6</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">mio</span><span class="o">-</span><span class="n">extras</span><span class="o">-</span><span class="mi">2</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="w"> </span><span class="p">(</span><span class="o">>=</span><span class="w"> </span><span class="mf">2.0</span><span class="o">.</span><span class="mi">5</span><span class="o">-~~</span><span class="p">),</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">nix</span><span class="o">-</span><span class="mf">0.17</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">slab</span><span class="o">-</span><span class="mf">0.4</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">structopt</span><span class="o">-</span><span class="mf">0.3</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">url</span><span class="o">-</span><span class="mi">2</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="w"> </span><span class="p">(</span><span class="o">>=</span><span class="w"> </span><span class="mf">2.1</span><span class="o">-~~</span><span class="p">),</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">zbus</span><span class="o">-</span><span class="mi">1</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span><span class="p">,</span>
<span class="w"> </span><span class="n">librust</span><span class="o">-</span><span class="n">zvariant</span><span class="o">-</span><span class="mi">2</span><span class="o">+</span><span class="n">default</span><span class="o">-</span><span class="n">dev</span>
</code></pre></div>
<p>By this:</p>
<div class="highlight"><pre><span></span><code>Build-Depends: debhelper (>= 12),
dh-cargo (>= 17),
cargo:native,
rustc:native,
libstd-rust-dev,
pkg-config,
libglib2.0-dev,
libslirp-dev
</code></pre></div>
<p>I wanted to keep the delta to the future Debian package at a bare minimum, so I kept the original <code>dh-cargo</code> build process, only making sure the vendored dependencies are found in the right place. The cleanest approach in my view was to use the fact that the <code>3.0 (quilt)</code> source format allows multiple original tarballs: the main tarball would be the same orig tarball as in Debian, and an extra tarball would contain the vendored code. When we sync with Debian, the extra tarball would be dropped, just as the adjustments to the <code>debian/rules</code>.</p>
<p>To generate the vendor tarball, I added this to the rules file:</p>
<div class="highlight"><pre><span></span><code><span class="cp">include /usr/share/dpkg/pkg-info.mk</span>
<span class="nf">vendor</span><span class="o">:</span>
<span class="w"> </span>-<span class="o">[</span><span class="w"> </span>-d<span class="w"> </span>vendor<span class="w"> </span><span class="o">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span>rm<span class="w"> </span>-rf<span class="w"> </span>vendor
<span class="w"> </span>rm<span class="w"> </span>-rf<span class="w"> </span>Cargo.lock
<span class="w"> </span>cargo<span class="w"> </span>vendor
<span class="w"> </span>tar<span class="w"> </span>Jcf<span class="w"> </span>../<span class="k">$(</span>DEB_SOURCE<span class="k">)</span>_<span class="k">$(</span>DEB_VERSION_UPSTREAM<span class="k">)</span>.orig-vendor.tar.xz<span class="w"> </span>vendor/
<span class="nf">.PHONY</span><span class="o">:</span><span class="w"> </span><span class="n">vendor</span>
</code></pre></div>
<p>This target, being run manually and not as part of the build process, download the latest dependencies satisfying the requirements in <code>Cargo.toml</code> and rolls them into a vendor tarball.</p>
<p>Now, to make <code>dh-cargo</code> use the vendored code, we need to link it into the right place. <code>dh-cargo</code> creates a Cargo registry tree in a subdirectly under <code>debian/</code> where it symlinks crates from the Rust development packages. This extra code makes sure the vendored dependencies are available there too:</p>
<div class="highlight"><pre><span></span><code><span class="nf">override_dh_auto_configure</span><span class="o">:</span>
<span class="w"> </span>dh_auto_configure<span class="w"> </span><span class="nv">$@</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span>d<span class="w"> </span><span class="k">in</span><span class="w"> </span>vendor/*<span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">[</span><span class="w"> </span>-L<span class="w"> </span>debian/cargo_registry/<span class="nv">$$</span><span class="o">(</span>basename<span class="w"> </span><span class="nv">$$</span>d<span class="o">)</span><span class="w"> </span><span class="o">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span>rm<span class="w"> </span>debian/cargo_registry/<span class="nv">$$</span><span class="o">(</span>basename<span class="w"> </span><span class="nv">$$</span>d<span class="o">)</span><span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>ln<span class="w"> </span>-rs<span class="w"> </span><span class="nv">$$</span>d<span class="w"> </span>debian/cargo_registry<span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="k">done</span>
</code></pre></div>
<p>An important thing here is that if the build happens on a non-clean system, <code>dh-cargo</code> may have symlinked a system crate already installed — so we need to remove that symlink and replace it by ours. We build packages in clean chroots, so this is not that important, otherwise for reproducibility reasons it would be better to create the registry directory from scratch.</p>
<p>The final package can be found at the <a href="https://gitlab.apertis.org/pkg/rust-libslirp">Apertis GitLab</a>.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleUseful FFmpeg commands for video editing2020-08-16T14:33:32+02:002020-08-16T14:33:32+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2020-08-16:/2020/08/16/useful-ffmpeg-commands/<p>As a response to Antonio Terceiro’s <a href="https://terceiro.xyz/2020/08/15/useful-ffmpeg-commands-for-editing-video/">blog post</a>, I’m publishing some FFmpeg commands I’ve been using recently.</p>
<h4>Embedding subtitles</h4>
<p>Sometimes you have a video with subtitles in multiple languages and you don’t want to clutter the directory with a lot of similarly-named files — or maybe you …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2020/08/16/useful-ffmpeg-commands/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>As a response to Antonio Terceiro’s <a href="https://terceiro.xyz/2020/08/15/useful-ffmpeg-commands-for-editing-video/">blog post</a>, I’m publishing some FFmpeg commands I’ve been using recently.</p>
<h4>Embedding subtitles</h4>
<p>Sometimes you have a video with subtitles in multiple languages and you don’t want to clutter the directory with a lot of similarly-named files — or maybe you want to be able to easily transfer the video and subtitles at once. In this case, it may be useful to embed to subtitles directly into the video container file.</p>
<div class="highlight"><pre><span></span><code>ffmpeg -i video.mp4 -i video.eng.srt -map 0:v -map 0:a -c copy -map 1 \
-c:s:0 mov_text -metadata:s:s:0 language="eng" video-out.mp4
</code></pre></div>
<p>This commands recodes the subtitle file into a format appropriate for the MP4 container and embeds it with a metadata element telling the video player what language it is in. You can add multiple subtitles at once, or you can also transcode the audio to AAC while doing so (I found that a lot of Android devices can’t play Ogg Vorbis streams):</p>
<div class="highlight"><pre><span></span><code>ffmpeg -i video.mp4 -i video.deu.srt -i video.eng.srt -map 0:v -map 0:a \
-c:v copy -c:a aac -map 1 -c:s:0 mov_text -metadata:s:s:0 language="deu" \
-map 2 -c:s:1 mov_text -metadata:s:s:1 language="eng" video-out.mp4
</code></pre></div>
<h4>‘Hard’ subtitles</h4>
<p>Sometimes you need to play the video with subtitles on devices not supporting them. In that case, it may be useful to ‘hardcode’ the subtitles directly into the video stream:</p>
<div class="highlight"><pre><span></span><code>ffmpeg -i video.mp4 -vf subtitles=video.eng.srt video-out.mp4
</code></pre></div>
<p>Unfortunately, if you also want to apply more transformations to the video, it starts getting tricky, the <code>-vf</code> option is no longer enough:</p>
<div class="highlight"><pre><span></span><code><span class="n">ffmpeg</span><span class="w"> </span><span class="o">-</span><span class="n">i</span><span class="w"> </span><span class="n">video</span><span class="p">.</span><span class="n">mp4</span><span class="w"> </span><span class="o">-</span><span class="n">i</span><span class="w"> </span><span class="k">overlay</span><span class="p">.</span><span class="n">jpg</span><span class="w"> </span><span class="o">-</span><span class="k">filter</span><span class="err">:</span><span class="n">a</span><span class="w"> </span><span class="ss">"volume=10"</span><span class="w"> </span><span class="err">\</span>
<span class="w"> </span><span class="o">-</span><span class="n">filter_complex</span><span class="w"> </span><span class="s1">'[0:v][1:v]overlay[outv];[outv]subtitles=video.eng.srt'</span><span class="w"> </span><span class="err">\</span>
<span class="w"> </span><span class="n">video</span><span class="o">-</span><span class="k">out</span><span class="p">.</span><span class="n">mp4</span>
</code></pre></div>
<p>This command adds an overlay to the video stream (in my case I overlaid a full frame over the original video offering some explanations), increases the volume ten times and adds hard subtitles.</p>
<p>P.S. You can see the practical application of the above in this <a href="https://www.youtube.com/watch?v=i_PEv2SO2yU">video with a head of one of the electoral commissions in Belarus forcing the members of the staff to manipulate the voting results</a>. I transcribed the video in both Russian and English and encoded the English subtitles into the video.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleFollow-up on the train journey to FOSDEM2020-02-21T15:09:28+01:002020-02-21T15:09:28+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2020-02-21:/2020/02/21/fosdem-by-train-followup/<p>Here’s a recap of my train journey based on the <a href="https://threadreaderapp.com/thread/1222802145268899842.html">Twitter thread</a>
I kept posting as I travelled.</p>
<h2>To FOSDEM…</h2>
<p>The departure from Bratislava was <a href="/2020/01/28/fosdem-by-train/">as planned</a>:
<figure><img alt="Ready to depart from Bratislava hl. st." class="img-responsive" src="/images/posts/2020-02/departure-bratislava-hl-st.jpg" title="Ready to depart from Bratislava hl. st."><figcaption>Ready to depart from Bratislava hl. st.</figcaption></figure></p>
<p>Half an hour in Vienna was just enough for me to grab some coffee and …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2020/02/21/fosdem-by-train-followup/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Here’s a recap of my train journey based on the <a href="https://threadreaderapp.com/thread/1222802145268899842.html">Twitter thread</a>
I kept posting as I travelled.</p>
<h2>To FOSDEM…</h2>
<p>The departure from Bratislava was <a href="/2020/01/28/fosdem-by-train/">as planned</a>:
<figure><img alt="Ready to depart from Bratislava hl. st." class="img-responsive" src="/images/posts/2020-02/departure-bratislava-hl-st.jpg" title="Ready to depart from Bratislava hl. st."/><figcaption>Ready to depart from Bratislava hl. st.</figcaption></figure></p>
<p>Half an hour in Vienna was just enough for me to grab some coffee and breakfast and board the train to Frankfurt without a hurry:
<figure><img alt="Boarding a Deutsche Bahn ICE to Frankfurt am Main" class="img-responsive" src="/images/posts/2020-02/boarding-ice-to-frankfurt.jpg" title="Boarding a Deutsche Bahn ICE to Frankfurt am Main"/><figcaption>Boarding a Deutsche Bahn ICE to Frankfurt am Main</figcaption></figure></p>
<p>Unfortunately, soon after we left Linz and headed to Passau, the train broke down. Apparently, it powered down and the driver was struggling to reboot it. After more than an hour at Haiding, we finally departed with a huge delay:
<figure><img alt="ICE standing at a platform of a railway station at Haiding" class="img-responsive" src="/images/posts/2020-02/trapped-in-haiding.jpg" title="Trapped in Haiding near Linz"/><figcaption>Trapped in Haiding near Linz</figcaption></figure></p>
<p>Since the 18:29 train to Brussels I needed to catch in Frankfurt was the last one that day, I was put into a hotel Leonardo across the street from Frankfurt Hbf, paid by Deutsche Bahn, of course. By the time of our arrival in Frankfurt, the delay was 88 minutes.
<figure><img alt="Hotel room in Frankfurt am Main" class="img-responsive" src="/images/posts/2020-02/hotel-in-frankfurt.jpg" title="Hotel room in Frankfurt am Main"/><figcaption>Hotel room in Frankfurt am Main</figcaption></figure></p>
<p>Luckily, I didn’t have to convince Deutsche Bahn to let me sleep in the morning, they happily booked me (for free) onto a 10:29 ICE to Brussels so I had an opportunity to have a proper breakfast at the hotel and spend some time at Coffee Fellows at the station.
<figure><img alt="Frankfurt Hbf building in the morning" class="img-responsive" src="/images/posts/2020-02/guten-morgen-frankfurt.jpg" title="Guten Morgen Frankfurt"/><figcaption>Guten Morgen Frankfurt</figcaption></figure>
<figure><img alt="ICE 16 to Brussels waiting at platform 19" class="img-responsive" src="/images/posts/2020-02/en-route-to-bxl.jpg" title="About to depart for Brussels"/><figcaption>About to depart for Brussels</figcaption></figure></p>
<p>Fun fact: Aachen is called Cáchy in Czech, apparently as a corruption of an older German form <em>ze Aachen</em>.
<figure><img alt="Platform sign saying Aachen Hbf with a double-decker red DB regional train" class="img-responsive" src="/images/posts/2020-02/stopping-at-aachen.jpg" title="Stopping at Aachen"/><figcaption>Stopping at Aachen</figcaption></figure></p>
<p>Having met some Debian people on the train, I have finally arrived in Brussels, albeit with some delay. This, unfortunately meant that I haven’t gone to Vilvoorde to see a friend, so the regional tickets I bought online were useless.
<figure><img alt="Platform at Bruxelles-Midi" class="img-responsive" src="/images/posts/2020-02/finally-bxl.jpg" title="Finally, Brussels!"/><figcaption>Finally, Brussels!</figcaption></figure></p>
<h2>… and back!</h2>
<p>The trip home was much better in terms of missed trains, only if a tiny bit more tiring since I took it in one day.
<figure><img alt="Platform at Bruxelles-Midi with an ICE almost ready to be boarded" class="img-responsive" src="/images/posts/2020-02/leaving-bxl.jpg" title="Leaving Brussels on time"/><figcaption>Leaving Brussels on time</figcaption></figure></p>
<p>Going to Frankfurt, I’ve spent most of the time in the bistro carriage. Unfortunately, the espresso machine was broken and they didn’t have any croissants, but the tea with milk was good enough.
<figure><img alt="In the bistro carriage" class="img-responsive" src="/images/posts/2020-02/in-the-bistrowagen.jpg" title="In the bistro carriage"/><figcaption>In the bistro carriage</figcaption></figure></p>
<p>I’ve used the fifty minutes I had in Frankfurt to claim the compensation for the delay, which (€33) I received in my bank account the next week.
<figure><img alt="The ICE train to Wien Hbf is about to depart" class="img-responsive" src="/images/posts/2020-02/departing-frankfurt-for-wien.jpg" title="The ICE train to Wien Hbf is about to depart"/><figcaption>The ICE train to Wien Hbf is about to depart</figcaption></figure>
<figure><img alt="The view out of the window: going along the river from Passau to Linz" class="img-responsive" src="/images/posts/2020-02/wilkommen-in-oesterreich.jpg" title="Herzlich willkommen in Österreich!"/><figcaption>Herzlich willkommen in Österreich!</figcaption></figure></p>
<p><figure><img alt="The ICE train at platform 11" class="img-responsive" src="/images/posts/2020-02/arrived-at-wien-hbf.jpg" title="Arrived at Wien Hbf"/><figcaption>Arrived at Wien Hbf</figcaption></figure>
<figure><img alt="The REX to Bratislava waiting at platform 4" class="img-responsive" src="/images/posts/2020-02/wien-to-bratislava.jpg" title="The last leg"/><figcaption>The last leg</figcaption></figure></p>
<p>Finally, exactly twelve hours and one minute after the departure, almost home:
<figure><img alt="The REX from Vienna arrived at platform 2" class="img-responsive" src="/images/posts/2020-02/arrived-at-bratislava-hl-st.jpg" title="Finally home"/><figcaption>Finally home</figcaption></figure></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleUsing gcc sanitisers to get a nasty bug fixed2020-01-31T12:35:45+01:002020-01-31T12:35:45+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2020-01-31:/2020/01/31/fsanitize-address/<p>A couple of days ago a colleague at <a href="https://www.collabora.com/">Collabora</a> asked me to help create a Debian package for the tool he needed to complete his task. The tool happened to be an NXP code signing tool, used to sign OS images to be run on i.MX systems using ‘<em>High …</em><footer><a rel="full-article" class="read-more btn btn-primary" href="/2020/01/31/fsanitize-address/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>A couple of days ago a colleague at <a href="https://www.collabora.com/">Collabora</a> asked me to help create a Debian package for the tool he needed to complete his task. The tool happened to be an NXP code signing tool, used to sign OS images to be run on i.MX systems using ‘<em>High Assurance Boot</em>’.</p>
<p>As it often happens, the tool was distributed in a manner typical for many big corporations: no direct link to the tarball, custom buildsystem, compiled binaries in the same tarball as the sources. A big relief was that the tool has been distributed under a three-clause BSD license since version 3.3.0 (the sources were not provided at all before that).</p>
<p>The custom buildsystem meant it was not using the Debian build flags (<code>CFLAGS := …</code>, <code>CC := gcc</code>), so I had to plug a custom ‘toolchain’ Makefile into the right place with definitions relevant to Debian:</p>
<div class="highlight"><pre><span></span><code><span class="nv">DPKG_EXPORT_BUILDTOOLS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span>
<span class="cp">include /usr/share/dpkg/buildtools.mk</span>
<span class="nv">LD</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">$(</span>CC<span class="k">)</span>
<span class="nv">COPTIONS</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span>-std<span class="o">=</span>c99<span class="w"> </span>-D_POSIX_C_SOURCE<span class="o">=</span>200809L<span class="w"> </span>-fPIC<span class="w"> </span><span class="k">$(</span>shell<span class="w"> </span>dpkg-buildflags<span class="w"> </span>--get<span class="w"> </span>CPPFLAGS<span class="k">)</span><span class="w"> </span><span class="k">$(</span>shell<span class="w"> </span>dpkg-buildflags<span class="w"> </span>--get<span class="w"> </span>CFLAGS<span class="k">)</span>
<span class="nv">LDOPTIONS</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="k">$(</span>shell<span class="w"> </span>dpkg-buildflags<span class="w"> </span>--get<span class="w"> </span>LDFLAGS<span class="k">)</span>
</code></pre></div>
<p>After some time of playing with the build system, the package was done and sent to a colleague pending an upload to Debian. What did worry me a bit was a weird warning the compiler gave me every time:</p>
<div class="highlight"><pre><span></span><code>../../code/front_end/src/acst.c:<span class="w"> </span>In<span class="w"> </span><span class="k">function</span><span class="w"> </span>‘encrypt_images’:
../../code/front_end/src/acst.c:791:25:<span class="w"> </span>warning:<span class="w"> </span>argument<span class="w"> </span><span class="m">1</span><span class="w"> </span>value<span class="w"> </span>‘18446744073709551615’<span class="w"> </span>exceeds<span class="w"> </span>maximum<span class="w"> </span>object<span class="w"> </span>size<span class="w"> </span><span class="m">9223372036854775807</span><span class="w"> </span><span class="o">[</span>-Walloc-size-larger-than<span class="o">=]</span>
<span class="w"> </span><span class="m">791</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>uint8_t<span class="w"> </span>*hash<span class="w"> </span><span class="o">=</span><span class="w"> </span>malloc<span class="o">(</span>hash_size<span class="o">)</span><span class="p">;</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>^~~~~~~~~~~~~~~~~
</code></pre></div>
<p>We didn’t use encryption, so I didn’t feel motivated to investigate.</p>
<p>Bad move.</p>
<p>Next day, the colleague comes back to me with this:</p>
<blockquote>
<p>I did test builds in Apertis SDK, Debian buster, Fedora 31, ALT Linux 9 -- only the latter environment produced the <code>cst</code> tool which generated correct signature for the file.</p>
<p>The rest produce a bit different signature with zeroes for the current kernel:</p>
<div class="highlight"><pre><span></span><code><span class="mf">000007</span><span class="n">E9</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">30</span>
<span class="mf">000007</span><span class="n">EA</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">82</span>
<span class="mf">000007</span><span class="n">EB</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">01</span>
<span class="mf">000007</span><span class="n">EC</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">F9</span>
<span class="mf">00000</span><span class="n">D41</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">30</span>
<span class="mf">00000</span><span class="n">D42</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">82</span>
<span class="mf">00000</span><span class="n">D43</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">01</span>
<span class="mf">00000</span><span class="n">D44</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">F9</span>
</code></pre></div>
<p>I found that the problem is related to compilation of <code>code/front_end/src/cst.c</code>.</p>
</blockquote>
<p>The colleague sent me a tarball with the working binary and a simple test case.</p>
<h3>First attempt</h3>
<p>Okay, let’s see. What are those eight different bytes? The signing tool comes with a utility, <code>csf_parser</code> to look inside of the signed file and extract bits and pieces. With debug logs on, for the correctly signed file the logs say this:</p>
<div class="highlight"><pre><span></span><code>CSF TAG: 0xD8
Parsing following values
0xD8 0x02 0x01 0x40 0x30 0x82 0x01 0xF9 0x06 …
</code></pre></div>
<p>The incorrectly signed one has this:</p>
<div class="highlight"><pre><span></span><code>CSF TAG: 0xD8
Parsing following values
0xD8 0x02 0x01 0x40 0x00 0x00 0x00 0x00 0x06 …
</code></pre></div>
<p>What’s 0xD8? <code>hab_types.h</code> says:</p>
<div class="highlight"><pre><span></span><code><span class="cp">#define HAB_TAG_SIG 0xd8 </span><span class="cm">/**< Signature */</span>
</code></pre></div>
<p>Apparently, the first four bytes are a header of the data chunk, so the differing bytes are part of the signature itself.</p>
<p>Let’s add some debug prints to see what’s going on. Oh no: now the difference is not just 8 bytes, but much more. Looks like there’s some memory corruption or undefined behaviour or maybe both.</p>
<p>Meanwhile, the colleague chimes in: he tried linking <code>cst.o</code> from ALT Linux with the rest of the program built on Debian, and produced a working binary.</p>
<h3>The dead end: disassembly</h3>
<p>My first thought was: oh, it’s just some code relying on undefined behaviour, what if I decompiled both object files and compared them?</p>
<p>In the past, when I needed to disassemble something I used IDA, but since it’s proprietary, I never had a license for it, and I don’t have it anymore anyway, it was not an option. It did, however, have a very good decompilation module which produced mostly readable C-like pseudocode.</p>
<p>When a couple of years ago I looked for a free software replacement for IDA, radare seemed like it had some potential, but it didn’t seem ready, and it wasn’t fully packaged for Debian. The things have changed, and not only radare is in Debian, but it also comes with a GUI, Cutter, which is very good, even though there’s always toom for improvement.</p>
<p>To my surprise, it turned out radare also has some decompilation functionality which worked really well.</p>
<p>Anyway, I won’t go further into it since this experiment didn’t give me any useful data to work with.</p>
<h3>Trying it with gdb</h3>
<p>Good, so the code at fault is somewhere close to the signing functions, so let’s try and debug it.</p>
<p>I rarely use the command-line gdb for anything else than printing backtraces, so here’s a small cheatsheet for the next time I need it:</p>
<ul>
<li><code>break -func create_sig_file</code>: set breakpoint at a function</li>
<li><code>finish</code>: ‘step out’, run to the end of the current function and stop right after it returns</li>
<li><code>x/10xb pointer</code>: print <strong>10</strong> he<strong>x</strong>adecimal <strong>b</strong>ytes</li>
</ul>
<p>This is what I have figured during my debugging session: the data gets corrupted at the end of the signing sequence, inside or before the <code>cms_to_buf</code> function invocation, which gets the signature data copied from the internal OpenSSL data structure into the output buffer:</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="n">gdb</span><span class="p">)</span><span class="w"> </span><span class="n">finish</span>
<span class="n">Run</span><span class="w"> </span><span class="n">till</span><span class="w"> </span><span class="k">exit</span><span class="w"> </span><span class="k">from</span><span class="w"> </span><span class="n">#0</span><span class="w"> </span><span class="n">cms_to_buf</span><span class="w"> </span><span class="p">(</span><span class="n">cms</span><span class="o">=</span><span class="n">cms</span><span class="nv">@entry</span><span class="o">=</span><span class="mh">0x555555598a60</span><span class="p">,</span><span class="w"> </span><span class="n">bio_in</span><span class="o">=</span><span class="n">bio_in</span><span class="nv">@entry</span><span class="o">=</span><span class="mh">0x555555597ff0</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="n">data_buffer</span><span class="o">=</span><span class="n">data_buffer</span><span class="nv">@entry</span><span class="o">=</span><span class="mh">0x7fffffffd380</span><span class="w"> </span><span class="ss">"\003"</span><span class="p">,</span><span class="w"> </span><span class="n">data_buffer_size</span><span class="o">=</span><span class="n">data_buffer_size</span><span class="nv">@entry</span><span class="o">=</span><span class="mh">0x7fffffffd37c</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="n">flags</span><span class="o">=</span><span class="n">flags</span><span class="nv">@entry</span><span class="o">=</span><span class="mi">17090</span><span class="p">)</span><span class="w"> </span><span class="k">at</span><span class="w"> </span><span class="p">..</span><span class="o">/</span><span class="p">..</span><span class="o">/</span><span class="n">code</span><span class="o">/</span><span class="n">back_end</span><span class="o">/</span><span class="n">src</span><span class="o">/</span><span class="n">adapt_layer_openssl</span><span class="p">.</span><span class="nl">c</span><span class="p">:</span><span class="mi">364</span>
<span class="mh">0x0000555555564399</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">gen_sig_data_cms</span><span class="w"> </span><span class="p">(</span><span class="n">sig_buf_bytes</span><span class="o">=</span><span class="mh">0x7fffffffd37c</span><span class="p">,</span><span class="w"> </span><span class="n">sig_buf</span><span class="o">=</span><span class="mh">0x7fffffffd380</span><span class="w"> </span><span class="ss">""</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="n">hash_alg</span><span class="o">=<</span><span class="n">optimised</span><span class="w"> </span><span class="k">out</span><span class="o">></span><span class="p">,</span><span class="w"> </span><span class="n">key_file</span><span class="o">=</span><span class="mh">0x555555578f70</span><span class="w"> </span><span class="ss">"IMG1_1_sha256_2048_65537_v3_usr_key.pem"</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="n">cert_file</span><span class="o">=</span><span class="mh">0x555555591440</span><span class="w"> </span><span class="ss">"IMG1_1_sha256_2048_65537_v3_usr_crt.pem"</span><span class="p">,</span><span class="w"> </span><span class="n">in_file</span><span class="o">=<</span><span class="n">optimised</span><span class="w"> </span><span class="k">out</span><span class="o">></span><span class="p">)</span>
<span class="w"> </span><span class="k">at</span><span class="w"> </span><span class="p">..</span><span class="o">/</span><span class="p">..</span><span class="o">/</span><span class="n">code</span><span class="o">/</span><span class="n">back_end</span><span class="o">/</span><span class="n">src</span><span class="o">/</span><span class="n">adapt_layer_openssl</span><span class="p">.</span><span class="nl">c</span><span class="p">:</span><span class="mi">487</span>
<span class="mi">487</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">..</span><span class="o">/</span><span class="p">..</span><span class="o">/</span><span class="n">code</span><span class="o">/</span><span class="n">back_end</span><span class="o">/</span><span class="n">src</span><span class="o">/</span><span class="n">adapt_layer_openssl</span><span class="p">.</span><span class="n">c</span>
<span class="k">Value</span><span class="w"> </span><span class="n">returned</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="err">$</span><span class="mi">2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="p">(</span><span class="n">gdb</span><span class="p">)</span><span class="w"> </span><span class="n">x</span><span class="o">/</span><span class="mi">10</span><span class="n">xb</span><span class="w"> </span><span class="mh">0x7fffffffd380</span>
<span class="mh">0x7fffffffd380</span><span class="err">:</span><span class="w"> </span><span class="mh">0x00</span><span class="w"> </span><span class="mh">0x00</span><span class="w"> </span><span class="mh">0x00</span><span class="w"> </span><span class="mh">0x00</span><span class="w"> </span><span class="mh">0x06</span><span class="w"> </span><span class="mh">0x09</span><span class="w"> </span><span class="mh">0x2a</span><span class="w"> </span><span class="mh">0x86</span>
<span class="mh">0x7fffffffd388</span><span class="err">:</span><span class="w"> </span><span class="mh">0x48</span><span class="w"> </span><span class="mh">0x86</span>
<span class="p">(</span><span class="n">gdb</span><span class="p">)</span><span class="w"> </span><span class="n">finish</span>
<span class="n">Run</span><span class="w"> </span><span class="n">till</span><span class="w"> </span><span class="k">exit</span><span class="w"> </span><span class="k">from</span><span class="w"> </span><span class="n">#0</span><span class="w"> </span><span class="n">cms_to_buf</span><span class="w"> </span><span class="p">(</span><span class="n">cms</span><span class="o">=</span><span class="mh">0x445290</span><span class="p">,</span><span class="w"> </span><span class="n">bio_in</span><span class="o">=</span><span class="mh">0x444800</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="n">data_buffer</span><span class="o">=</span><span class="mh">0x7fffffffcbe0</span><span class="w"> </span><span class="ss">"P\320\377\377\377\177"</span><span class="p">,</span><span class="w"> </span><span class="n">data_buffer_size</span><span class="o">=</span><span class="mh">0x7fffffffcbcc</span><span class="p">,</span><span class="w"> </span><span class="n">flags</span><span class="o">=</span><span class="mi">17090</span><span class="p">)</span>
<span class="w"> </span><span class="k">at</span><span class="w"> </span><span class="p">..</span><span class="o">/</span><span class="p">..</span><span class="o">/</span><span class="n">code</span><span class="o">/</span><span class="n">back_end</span><span class="o">/</span><span class="n">src</span><span class="o">/</span><span class="n">adapt_layer_openssl</span><span class="p">.</span><span class="nl">c</span><span class="p">:</span><span class="mi">365</span>
<span class="mh">0x00000000004109f6</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">gen_sig_data_cms</span><span class="w"> </span><span class="p">(</span><span class="n">in_file</span><span class="o">=</span><span class="mh">0x416553</span><span class="w"> </span><span class="ss">"imgsig.bin"</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="n">cert_file</span><span class="o">=</span><span class="mh">0x43dc50</span><span class="w"> </span><span class="ss">"IMG1_1_sha256_2048_65537_v3_usr_crt.pem"</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="n">key_file</span><span class="o">=</span><span class="mh">0x43d640</span><span class="w"> </span><span class="ss">"IMG1_1_sha256_2048_65537_v3_usr_key.pem"</span><span class="p">,</span><span class="w"> </span><span class="n">hash_alg</span><span class="o">=</span><span class="n">SHA_256</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="n">sig_buf</span><span class="o">=</span><span class="mh">0x7fffffffcbe0</span><span class="w"> </span><span class="ss">"0\202\001\371\006\t*"</span><span class="p">...,</span><span class="w"> </span>
<span class="w"> </span><span class="n">sig_buf_bytes</span><span class="o">=</span><span class="mh">0x7fffffffcbcc</span><span class="p">)</span><span class="w"> </span><span class="k">at</span><span class="w"> </span><span class="p">..</span><span class="o">/</span><span class="p">..</span><span class="o">/</span><span class="n">code</span><span class="o">/</span><span class="n">back_end</span><span class="o">/</span><span class="n">src</span><span class="o">/</span><span class="n">adapt_layer_openssl</span><span class="p">.</span><span class="nl">c</span><span class="p">:</span><span class="mi">487</span>
<span class="mi">487</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="p">..</span><span class="o">/</span><span class="p">..</span><span class="o">/</span><span class="n">code</span><span class="o">/</span><span class="n">back_end</span><span class="o">/</span><span class="n">src</span><span class="o">/</span><span class="n">adapt_layer_openssl</span><span class="p">.</span><span class="n">c</span>
<span class="k">Value</span><span class="w"> </span><span class="n">returned</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="err">$</span><span class="mi">5</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="p">(</span><span class="n">gdb</span><span class="p">)</span><span class="w"> </span><span class="n">x</span><span class="o">/</span><span class="mi">10</span><span class="n">xb</span><span class="w"> </span><span class="mh">0x7fffffffcbe0</span>
<span class="mh">0x7fffffffcbe0</span><span class="err">:</span><span class="w"> </span><span class="mh">0x30</span><span class="w"> </span><span class="mh">0x82</span><span class="w"> </span><span class="mh">0x01</span><span class="w"> </span><span class="mh">0xf9</span><span class="w"> </span><span class="mh">0x06</span><span class="w"> </span><span class="mh">0x09</span><span class="w"> </span><span class="mh">0x2a</span><span class="w"> </span><span class="mh">0x86</span>
<span class="mh">0x7fffffffcbe8</span><span class="err">:</span><span class="w"> </span><span class="mh">0x48</span><span class="w"> </span><span class="mh">0x86</span>
</code></pre></div>
<h3>Trying it with splint and valgrind</h3>
<p>Having failed to find the data corruption by manually inspecting the source, I tried enabling every compiler warning I could, which gave me no results, and then decided to use external tools to help me with that.</p>
<p>First comes <em>splint</em>, a C linter. It produced about a thousand warnings and errors which, while probably were at least partially valid, completely overwhelmed me.</p>
<p>Next came <em>valgrind</em>, which, even at the most aggressive settings only pointed me at uninitialised padding data in some structures:</p>
<div class="highlight"><pre><span></span><code><span class="n">number</span><span class="o">:</span><span class="w"> </span><span class="n">NUMBER</span>
<span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">$$</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">malloc</span><span class="o">(</span><span class="n">sizeof</span><span class="o">(</span><span class="n">number_t</span><span class="o">));</span>
<span class="w"> </span><span class="n">$$</span><span class="o">-></span><span class="n">next</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">NULL</span><span class="o">;</span>
<span class="w"> </span><span class="n">$$</span><span class="o">-></span><span class="n">num_value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">$1</span><span class="o">;</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">;</span>
</code></pre></div>
<p>And, of course, OpenSSL was reading uninitialised data to improve the randomness.</p>
<p>Not very helpful.</p>
<h3>Almost giving up</h3>
<p>Since I have spent most of the day debugging, valgrinding, reading code and worrying about my soon to be missed <a href="/2020/01/28/fosdem-by-train/">connection to Brussels in Frankfurt</a>, I became very frustrated about having no useful results and was close to giving up and calling it a day.</p>
<p>As a last chance attempt, I decided to try all hardening options I could find in the GCC manual page and on the Debian wiki.</p>
<p>First, <code>DEB_BUILD_MAINT_OPTIONS = hardening=+all</code>, <code>-fPIE -pie</code>. Not much changed. Or rather nothing at all.</p>
<p>Then, I found sanitisers. Okay, dump it all into the makefile: <code>-fsanitize=address -fsanitize=undefined -fsanitize=leak -fno-omit-frame-pointer</code>. Compile, link, run: nothing works. Apparently, they need link options as well: <code>-static-libasan -static-libubsan -static-liblsan</code></p>
<p><figure><img alt="Colourful address sanitiser output" class="img-responsive" src="/images/posts/asan.png" title="Colourful address sanitiser output"/><figcaption>Colourful address sanitiser output</figcaption></figure></p>
<p>Cracked it!</p>
<div class="highlight"><pre><span></span><code><span class="cm">/**</span>
<span class="cm"> * sig_size as input to gen_sig_data shows the size of buffer for</span>
<span class="cm"> * signature data and gen_sig_data returns actual size of signature</span>
<span class="cm"> * data in this argument</span>
<span class="cm"> */</span>
<span class="kt">uint32_t</span><span class="w"> </span><span class="n">sig_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SIGNATURE_BUFFER_SIZE</span><span class="p">;</span>
<span class="p">...</span>
<span class="cm">/**</span>
<span class="cm"> * Calling gen_sig_data to generate signature for data in file using</span>
<span class="cm"> * certificate in cert_file. The signature data will be returned in</span>
<span class="cm"> * sig and size of signature data in sig_size</span>
<span class="cm"> */</span>
<span class="n">ret_val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gen_sig_data</span><span class="p">(</span><span class="n">file</span><span class="p">,</span><span class="w"> </span><span class="n">cert_file</span><span class="p">,</span><span class="w"> </span><span class="n">hash</span><span class="p">,</span><span class="w"> </span><span class="n">sig_fmt</span><span class="p">,</span>
<span class="w"> </span><span class="n">sig</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">size_t</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">sig_size</span><span class="p">,</span><span class="w"> </span><span class="n">g_mode</span><span class="p">);</span>
</code></pre></div>
<p>Of course, <code>size_t</code> is 32-bit on 32-bit systems, but <em>significantly</em> wider on 64-bit ones, so no surprise this code would overwrite something else on the stack, in this case the signature data.</p>
<p>One of the lessons I learnt from this way: never underestimate the compiler’s built-in tools. At least, not the sanitisers!</p>
<p>Oh, just in case you want to see more: the patches currently live at the <a href="https://gitlab.apertis.org/pkg/development/imx-code-signing-tool/merge_requests/2/">Apertis GitLab</a>.</p>
<p><strong>2020-02-18 Update</strong>: This post has also been published at Collabora’s website: <a href="https://www.collabora.com/news-and-blog/blog/2020/02/18/using-gcc-sanitisers-to-get-a-nasty-bug-fixed">https://www.collabora.com/news-and-blog/blog/2020/02/18/using-gcc-sanitisers-to-get-a-nasty-bug-fixed</a></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleFOSDEM by train2020-01-28T20:18:00+01:002020-01-28T20:18:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2020-01-28:/2020/01/28/fosdem-by-train/<p>I’ve always loved train journeys, but with <em>flygskam</em> changing people’s travel preferences across Europe
(and possibly worldwide, though probably not that much), I decided to take train to <a href="https://fosdem.org">FOSDEM</a> this time.</p>
<p>When I first went to FOSDEM which, just in case you don’t know, happens each February …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2020/01/28/fosdem-by-train/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>I’ve always loved train journeys, but with <em>flygskam</em> changing people’s travel preferences across Europe
(and possibly worldwide, though probably not that much), I decided to take train to <a href="https://fosdem.org">FOSDEM</a> this time.</p>
<p>When I first went to FOSDEM which, just in case you don’t know, happens each February in Brussels at <a href="https://www.ulb.be">ULB</a>,
I flew with Ryanair from Bratislava to Charleroi because it was cheaper. After repeating the same journey
a couple of times and I once nearly missed the last bus coach to Brussels because of a late flight, and decided to
rather pay more but travel with more comfort to Brussels Zaventem, the main airport of Brussels. It’s well-connected
with Brussels, trains run fast and run often, which is a significant upgrade in comparison to Charleroi,
where the options were limited to bus coaches and a slow train connection from Charleroi the town.</p>
<p>As some of my readers may know, my backpack was stolen from me after FOSDEM two years ago, and with it
were gone, among other things, my passport and my residence permit card. With my flight home having been
planned two and half hours from the moment when I realised my things are gone, I couldn’t get a replacement
travel document quickly enough from the embassy, so I had to stay at my friends in Vilvoorde (thanks a lot again,
Jurgen!) and travel with the cheapest ground transportation I could find. In my case, it was a night RegioJet coach
to Prague with a connection to (again) RegioJet train to Bratislava. (I couldn’t fly even though I already had my
temporary travel document since I might need to somehow prove that I’m allowed to be in the Schengen zone, which
is difficult to do without a valid residence permit.) Sleeping on a bus isn’t the best way to travel for long
distances, and I was knackered when I finally dropped on my sofa in Bratislava next morning. However, what I
learnt was that it was possible, and were it a bit more comfortable, I wouldn’t mind something like this again.</p>
<p>Here I must admit that I’ve travelled by long-distance trains quite a fair bit: in my childhood we went by train to summer holidays
to <a href="https://en.wikipedia.org/wiki/Yevpatoria">Eupatoria</a> in Crimea and <a href="https://en.wikipedia.org/wiki/Obzor">Obzor</a> in Bulgaria (through <a href="https://en.wikipedia.org/wiki/Varna">Varna</a>). Both journeys took days, and the latter also involved a long
process of changing the bogies on the Moldovan-Romanian border (Giurgiulești/Galați). Since I moved to Slovakia, I many times took
the night train from Minsk to Warsaw with a connection to Bratislava or Žilina, a journey which usually takes at least 18 hours.
Which is to say, I’m not exactly new to this mode of travel.</p>
<p>With the Austrian railway company <a href="https://www.oebb.at">ÖBB</a> expaning their night train services as a part of their Nightjet brand,
the <a href="https://www.theguardian.com/world/2020/jan/20/brussels-vienna-night-train-returns-as-europe-eyes-flying-alternatives">Vienna to Brussels sleeper returned to service last week</a>. Prices are still a bit higher than I would have
preferred (at the time of me writing this, ticket in a compartment with 6 <em>couchettes</em> start at €79, but it’s not
as bad as it could be (apparently the last minute price is more than €200). Anyway, when I decided to go to Brussels
by train, this service didn’t exist yet, so instead I followed the very useful tips from the <a href="https://www.seat61.com/Austria.htm">Man in the Seat 61</a> and
booked a day-time connection: Bratislava to Vienna to Frankfurt to Brussels.</p>
<p><figure><img alt="Train route from Bratislava to Vienna to Frankfurt to Brussels" class="img-responsive" src="/images/posts/fosdem-by-train.jpg" title="Train route from Bratislava to Vienna to Frankfurt to Brussels"/><figcaption>Train route from Bratislava to Vienna to Frankfurt to Brussels</figcaption></figure></p>
<table class="table table-striped">
<thead>
<tr>
<th>Date</th>
<th>Station</th>
<th>Arrival</th>
<th>Departure</th>
<th>Train</th>
</tr>
</thead>
<tbody>
<tr>
<td>30.1</td>
<td>Bratislava hl.st.</td>
<td></td>
<td>9:38</td>
<td>REX 2511</td>
</tr>
<tr>
<td></td>
<td>Wien Hbf</td>
<td>10:44</td>
<td>11:15</td>
<td>ICE 26</td>
</tr>
<tr>
<td></td>
<td>Frankfurt am Main Hbf</td>
<td>17:36</td>
<td>18:29</td>
<td>ICE 10</td>
</tr>
<tr>
<td></td>
<td>Bruxelles-Nord / Brussel Noord</td>
<td>21:26</td>
<td>21:37</td>
<td>IC 3321</td>
</tr>
<tr>
<td></td>
<td>Vilvoorde</td>
<td>21:45</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<table class="table table-striped">
<thead>
<tr>
<th>Date</th>
<th>Station</th>
<th>Arrival</th>
<th>Departure</th>
<th>Train</th>
</tr>
</thead>
<tbody>
<tr>
<td>4.2</td>
<td>Bruxelles-Midi</td>
<td></td>
<td>8:23</td>
<td>ICE 13</td>
</tr>
<tr>
<td></td>
<td>Frankfurt am Main Hbf</td>
<td>11:31</td>
<td>12:22</td>
<td>ICE 27</td>
</tr>
<tr>
<td></td>
<td>Wien Hbf</td>
<td>18:45</td>
<td>19:16</td>
<td>R 2530</td>
</tr>
<tr>
<td></td>
<td>Bratislava hl.st.</td>
<td>20:22</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>I’ve booked two through tickets since in this case the <em>Super Sparschiene</em> discount offered lower prices than normally an international
return ticket would offer. For some reason neither <a href="https://www.zssk.sk">ZSSK</a> (Slovak railways) nor <a href="https://www.oebb.at">ÖBB</a> offered ticket online (or for a comparable
price in a ticket office anyway), so I booked online with <em><a href="https://reiseauskunft.bahn.de/">Deutsche Bahn</a></em> for €59.90 each way. This sort of ticket, while bookable online,
had to be <em>posted</em> for a €5.90 extra.</p>
<p>Since I’m staying the first night at friend’s in Vilvoorde again, I also had buy a ticket for this small stretch of the track from the Belgian railways
directly.</p>
<p>See you at FOSDEM!</p>
<p><figure><img alt="Building AW" class="img-responsive" src="/images/posts/fosdem-building-aw.jpg" title="Building AW"/><figcaption>Building AW</figcaption></figure>
<figure><img alt="Inside the K building" class="img-responsive" src="/images/posts/fosdem-building-k.jpg" title="Inside the K building"/><figcaption>Inside the K building</figcaption></figure>
<figure><img alt="Grand Place" class="img-responsive" src="/images/posts/brussels-grand-place.jpg" title="Grand Place"/><figcaption>Grand Place</figcaption></figure></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleRust-like enums in Kotlin2019-09-25T15:31:43+02:002019-09-25T15:31:43+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2019-09-25:/2019/09/25/kotlin-enums/<p>Rust has an exciting concept of enumeration types, which is much more powerful than enums in other languages.
Notably C has the weakest type of enum, since there’s no type checking of any kind, and enum values can be used interchangeably with integers:</p>
<div class="highlight"><pre><span></span><code><span class="k">enum</span><span class="w"> </span><span class="n">JobState</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">PENDING</span><span class="p">,</span>
<span class="w"> </span><span class="n">STARTED</span><span class="p">,</span>
<span class="w"> </span><span class="n">FAILED</span><span class="p">,</span>
<span class="w"> </span><span class="n">COMPLETED …</span></code></pre><footer><a rel="full-article" class="read-more btn btn-primary" href="/2019/09/25/kotlin-enums/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></div><p>Rust has an exciting concept of enumeration types, which is much more powerful than enums in other languages.
Notably C has the weakest type of enum, since there’s no type checking of any kind, and enum values can be used interchangeably with integers:</p>
<div class="highlight"><pre><span></span><code><span class="k">enum</span><span class="w"> </span><span class="n">JobState</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">PENDING</span><span class="p">,</span>
<span class="w"> </span><span class="n">STARTED</span><span class="p">,</span>
<span class="w"> </span><span class="n">FAILED</span><span class="p">,</span>
<span class="w"> </span><span class="n">COMPLETED</span>
<span class="p">};</span>
</code></pre></div>
<p>You can opt for manually assigning integers instead of leaving this to the compiler, but that’s about it.</p>
<p>Higher level languages like Python and Java treat enumeration types as classes, bringing stricted type checking and better flexibility, since they can be extended nearly as any other classes. In both Python and Java individual enumerated values are singleton instances of the enumeration class.</p>
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">JobState</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
<span class="n">PENDING</span> <span class="o">=</span> <span class="n">auto</span><span class="p">()</span>
<span class="n">STARTED</span> <span class="o">=</span> <span class="n">auto</span><span class="p">()</span>
<span class="n">FAILED</span> <span class="o">=</span> <span class="n">auto</span><span class="p">()</span>
<span class="n">COMPLETED</span> <span class="o">=</span> <span class="n">auto</span><span class="p">()</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="kd">enum</span><span class="w"> </span><span class="n">JobState</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">PENDING</span><span class="p">,</span>
<span class="w"> </span><span class="n">STARTED</span><span class="p">,</span>
<span class="w"> </span><span class="n">FAILED</span><span class="p">,</span>
<span class="w"> </span><span class="n">COMPLETED</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Since enumerations are classes, they can define extra methods, but because the enum values are singletons, they can’t be coupled with any extra data, and no new instances of the enum class can be created.</p>
<p>In contrast with Python and Java, Rust allows attaching data to enumerations:</p>
<div class="highlight"><pre><span></span><code><span class="k">enum</span> <span class="nc">JobState</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Pending</span><span class="p">,</span>
<span class="w"> </span><span class="n">Started</span><span class="p">,</span>
<span class="w"> </span><span class="n">Failed</span><span class="p">(</span><span class="nb">String</span><span class="p">),</span>
<span class="w"> </span><span class="n">Completed</span>
<span class="p">}</span>
</code></pre></div>
<p>This allows us to store the error message in the same value as the job state, without having to declare a structure with an extra field which would be used only when the state in <code>Failed</code>.</p>
<p>So, what Kotlin has to offer? Kotlin has a language feature called <em>sealed classes</em>. A sealed class is an abstract class with limited interitance: all of its subclasses have to be declated in the same file. In a way, this is quite close to the Rust enums, even though sealed classed look and behave a bit differently.</p>
<div class="highlight"><pre><span></span><code><span class="kd">sealed</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nc">JobState</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">object</span><span class="w"> </span><span class="nc">Pending</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">JobState</span><span class="p">()</span>
<span class="w"> </span><span class="kd">object</span><span class="w"> </span><span class="nc">Started</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">JobState</span><span class="p">()</span>
<span class="w"> </span><span class="kd">object</span><span class="w"> </span><span class="nc">Completed</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">JobState</span><span class="p">()</span>
<span class="w"> </span><span class="kd">data</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nc">Failed</span><span class="p">(</span><span class="kd">val</span><span class="w"> </span><span class="nv">errorMessage</span><span class="p">:</span><span class="w"> </span><span class="kt">String</span><span class="p">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">JobState</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div>
<p>Declared this way, <code>JobState</code> can be used in a way similar to Rust’s enums: a single variable of this type can be assigned singletons <code>Pending</code>, <code>Started</code> or <code>Completed</code>, or any instance of <code>Failed</code> with a mandatory <code>String</code> member:</p>
<div class="highlight"><pre><span></span><code><span class="kd">val</span><span class="w"> </span><span class="nv">state</span><span class="p">:</span><span class="w"> </span><span class="n">JobState</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">JobState</span><span class="p">.</span><span class="na">Failed</span><span class="p">(</span><span class="s">"I/O error"</span><span class="p">)</span>
<span class="k">when</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">JobState</span><span class="p">.</span><span class="na">Completed</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"Job completed"</span><span class="p">)</span>
<span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">JobState</span><span class="p">.</span><span class="na">Failed</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"Job failed with an error: </span><span class="si">${</span><span class="n">state</span><span class="p">.</span><span class="na">errorMessage</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div>
<p>This usage resembles the regular Java/Kotlin enums quite a bit, but alternatively, <code>Pending</code> and friends can be declared outside of the sealed class, allowing them to be used directly without the need to add a <code>JobState</code> qualifier.</p>
<p>A slightly simplified real life example from a Kotlin project I’m working on, where a separate coroutine handles I/O with a Bluetooth or a USB device:</p>
<div class="highlight"><pre><span></span><code><span class="kd">sealed</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nc">Result</span>
<span class="kd">object</span><span class="w"> </span><span class="nc">Connected</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">Result</span><span class="p">()</span>
<span class="kd">data</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nc">Failed</span><span class="p">(</span><span class="kd">val</span><span class="w"> </span><span class="nv">error</span><span class="p">:</span><span class="w"> </span><span class="kt">String</span><span class="p">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">Result</span><span class="p">()</span>
<span class="kd">sealed</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nc">CommServiceMsg</span>
<span class="kd">data</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nc">Connect</span><span class="p">(</span><span class="kd">val</span><span class="w"> </span><span class="nv">response</span><span class="p">:</span><span class="w"> </span><span class="n">CompletableDeferred</span><span class="o"><</span><span class="n">Result</span><span class="o">></span><span class="p">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">CommServiceMsg</span><span class="p">()</span>
<span class="kd">object</span><span class="w"> </span><span class="nc">Disconnect</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">CommServiceMsg</span><span class="p">()</span>
<span class="kd">data</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nc">Write</span><span class="p">(</span><span class="kd">val</span><span class="w"> </span><span class="nv">data</span><span class="p">:</span><span class="w"> </span><span class="n">ByteArray</span><span class="p">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">CommServiceMsg</span><span class="p">()</span>
<span class="kd">fun</span><span class="w"> </span><span class="n">CoroutineScope</span><span class="p">.</span><span class="nf">bluetoothServiceActor</span><span class="p">(</span><span class="n">device</span><span class="p">:</span><span class="w"> </span><span class="n">BluetoothDevice</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">actor</span><span class="o"><</span><span class="n">CommServiceMsg</span><span class="o">></span><span class="p">(</span><span class="n">Dispatchers</span><span class="p">.</span><span class="na">IO</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">socket</span><span class="p">:</span><span class="w"> </span><span class="n">BluetoothSocket</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">device</span><span class="p">.</span><span class="na">createSocket</span><span class="p">()</span>
<span class="w"> </span><span class="nd">process@</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">msg</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">channel</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">when</span><span class="w"> </span><span class="p">(</span><span class="n">msg</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">Connect</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">with</span><span class="p">(</span><span class="n">socket</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">msg</span><span class="p">.</span><span class="na">response</span><span class="p">.</span><span class="na">complete</span><span class="p">(</span><span class="k">try</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">connect</span><span class="p">()</span>
<span class="w"> </span><span class="n">Connected</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">e</span><span class="p">:</span><span class="w"> </span><span class="n">IOException</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">error</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">e</span><span class="p">.</span><span class="na">message</span><span class="w"> </span><span class="o">?:</span><span class="w"> </span><span class="s">""</span>
<span class="w"> </span><span class="n">Failed</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">Disconnect</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="k">break</span><span class="nd">@process</span>
<span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">Write</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">socket</span><span class="p">.</span><span class="na">outputStream</span><span class="p">.</span><span class="na">write</span><span class="p">(</span><span class="n">msg</span><span class="p">.</span><span class="na">data</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">socket</span><span class="p">.</span><span class="na">outputStream</span><span class="p">.</span><span class="na">flush</span><span class="p">()</span>
<span class="w"> </span><span class="n">socket</span><span class="p">.</span><span class="na">close</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div>
<p>Here, we can talk to <code>bluetoothServiceActor</code> using messages each carrying extra data; if the coroutine needs to talk back (in this example, the result of a connection attempt), it uses a <code>CompletableDeferred<></code> value of the <code>Result</code> type, which can hold an error message when needed.</p>
<p>With that in place, we can write something like this:</p>
<div class="highlight"><pre><span></span><code><span class="kd">val</span><span class="w"> </span><span class="nv">bluetoothService</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bluetoothServiceActor</span><span class="p">(</span><span class="n">device</span><span class="p">)</span>
<span class="kd">val</span><span class="w"> </span><span class="nv">response</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">CompletableDeferred</span><span class="o"><</span><span class="n">Result</span><span class="o">></span><span class="p">()</span>
<span class="n">bluetoothService</span><span class="p">.</span><span class="na">send</span><span class="p">(</span><span class="n">Connect</span><span class="p">(</span><span class="n">response</span><span class="p">))</span>
<span class="kd">var</span><span class="w"> </span><span class="nv">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">response</span><span class="p">.</span><span class="na">await</span><span class="p">()</span>
<span class="k">when</span><span class="w"> </span><span class="p">(</span><span class="n">result</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">Connected</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">bluetoothService</span><span class="p">.</span><span class="na">send</span><span class="p">(</span><span class="n">Write</span><span class="p">(</span><span class="n">byteArrayOf</span><span class="p">(</span><span class="m">42</span><span class="p">,</span><span class="w"> </span><span class="m">0</span><span class="n">x1e</span><span class="p">,</span><span class="w"> </span><span class="m">0</span><span class="n">x17</span><span class="p">)))</span>
<span class="w"> </span><span class="n">bluetoothService</span><span class="p">.</span><span class="na">send</span><span class="p">(</span><span class="n">Disconnect</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">Failed</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"error occurred: </span><span class="si">${</span><span class="n">result</span><span class="p">.</span><span class="na">error</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleBug Squashing Party: Bratislava, 9/10 February 20192019-01-24T11:49:00+01:002019-01-24T11:49:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2019-01-24:/2019/01/24/bratislava-bsp/<p>As I <a href="https://lists.debian.org/debian-events-eu/2019/01/msg00002.html">previously announced</a>, I’m organising a <a href="https://wiki.debian.org/BSP">BSP</a> <a href="https://wiki.debian.org/BSP/2019/02/sk/Bratislava">in Bratislava</a> during the weekend following FOSDEM. It will be happening at the same time as the <a href="https://wiki.debian.org/BSP/2019/02/de/Berlin">BSP in Berlin</a>, so if it’s not practical or possible for you to come to Berlin, consider coming around here.</p>
<p>The venue this …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2019/01/24/bratislava-bsp/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>As I <a href="https://lists.debian.org/debian-events-eu/2019/01/msg00002.html">previously announced</a>, I’m organising a <a href="https://wiki.debian.org/BSP">BSP</a> <a href="https://wiki.debian.org/BSP/2019/02/sk/Bratislava">in Bratislava</a> during the weekend following FOSDEM. It will be happening at the same time as the <a href="https://wiki.debian.org/BSP/2019/02/de/Berlin">BSP in Berlin</a>, so if it’s not practical or possible for you to come to Berlin, consider coming around here.</p>
<p>The venue this time is <a href="https://lab.cafe/">Lab.cafe</a>, café/coworking space/maker space in the centre of Bratislava in the building of the old market hall.</p>
<p><a href="/images/posts/bratislava-stara-trznica-pano.jpg"><img alt="The old market hall in the winter" class="img-responsive" src="/images/posts/bratislava-stara-trznica-pano-resized.jpg" style="max-width: 80%;"/></a></p>
<p><a href="https://noizz.azet.sk/big-stories/coworking-lab-kaviaren/4zngqet"><img alt="Inside lab.cafe" class="img-responsive" src="https://ocdn.eu/pulscms-transforms/1/oiUk9kqTURBXy8wNzliM2ExYWY2ZGJlMDU5NTc2MDNhMjRkYjJjYTcyZS5qcGVnkZUCzQVWAMLDgaEwAQ" style="max-width: 80%;"/></a></p>
<p>The venue located at the boundary of the Old Town, so while it is easily accessible by foot or public transport, it is a bit complicated to reach by car.</p>
<p>If you’re not from Bratislava, you will likely be arriving by train (to the main station, <em>Bratislava hl.st.</em>) or bus/coach (to the bus station). From the train station, take tram number <a href="https://imhd.sk/ba/schedule-timetable/route-line/1"><strong>1</strong></a> to the stop <em>Námestie SNP</em>; the tram will stop in from of the market hall. If arriving by bus, it’s best to walk, but if you prefer buses, take either <a href="https://imhd.sk/ba/schedule-timetable/route-line/205"><strong>205</strong></a> or <a href="https://imhd.sk/ba/schedule-timetable/route-line/X72"><strong>X72</strong></a> to the final stop <em>Nemocnica sv. Michala</em>.</p>
<p><img src="https://wiki.debian.org/BSP/2019/02/sk/Bratislava?action=AttachFile&do=get&target=bratislava-train-to-labcafe.png" style="max-width: 40%;"/> <img src="https://wiki.debian.org/BSP/2019/02/sk/Bratislava?action=AttachFile&do=get&target=bratislava-bus-to-labcafe.png" style="max-width: 40%;"/></p>
<p>If you’re coming from Vienna, both train and coach timetables are available from <a href="https://cp.sk/">cp.sk</a>, e.g. by using <a href="https://cp.hnonline.sk/vlakbus/spojenie/?date=09.02.2019&time=7%3a00&f=Wien&t=Bratislava&fc=1&tc=1&lng=E&submit=true">this link</a>.</p>
<p>If you decide you’d like to attend, please sign up here: <a href="https://framadate.org/debian-bsp-bratislava-2019-02">https://framadate.org/debian-bsp-bratislava-2019-02</a>. Please indicate the which days you can attend, and whether you will be attending in before the lunch time or after or both.</p>
<p>For more up-to-date information, see the wiki page: <a href="https://wiki.debian.org/BSP/2019/02/sk/Bratislava">https://wiki.debian.org/BSP/2019/02/sk/Bratislava</a>.</p>
<p>See you at the bug squashing party!</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleresvg: worth having in Debian?2019-01-09T11:05:00+01:002019-01-09T11:05:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2019-01-09:/2019/01/09/resvg/<p>Yesterday I have discovered <a href="https://github.com/RazrFalcon/resvg">resvg</a>, an MPL 2.0-licensed SVG rendering and optimisation library and a tool, written in Rust. It is said to be faster than some SVG renderers while currently slower than librsvg. It aims to support the static subset of SVG <a href="https://razrfalcon.github.io/resvg-test-suite/svg-support-table.html">better</a> than other libraries:</p>
<p><img alt="SVG test suite results: resvg 1272, Inkscape 967, librsvg 998" src="https://raw.githubusercontent.com/RazrFalcon/resvg/master/.github/chart.svg?sanitize=true"></p>
<p>The author …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2019/01/09/resvg/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Yesterday I have discovered <a href="https://github.com/RazrFalcon/resvg">resvg</a>, an MPL 2.0-licensed SVG rendering and optimisation library and a tool, written in Rust. It is said to be faster than some SVG renderers while currently slower than librsvg. It aims to support the static subset of SVG <a href="https://razrfalcon.github.io/resvg-test-suite/svg-support-table.html">better</a> than other libraries:</p>
<p><img alt="SVG test suite results: resvg 1272, Inkscape 967, librsvg 998" src="https://raw.githubusercontent.com/RazrFalcon/resvg/master/.github/chart.svg?sanitize=true"/></p>
<p>The author writes:</p>
<blockquote>
<p>One of the major differences from other rendering libraries is that resvg does a lot of preprocessing before rendering. It converts shapes to paths, resolves attributes, removes groups and invisible elements, fixes a lot of issues in malformed SVG files. Then it creates a simple render tree with all elements and attributes resolved. And only then it starts to render. So it's very easy to implement a new rendering backend.</p>
<ul>
<li>librsvg, currently, is heavily tied to the cairo library, unlike resvg</li>
<li>librsvg is heavily tied to GNOME which makes it painful to distribute outside the Linux ecosystem</li>
<li>librsvg doesn't really preprocess input files, rendering them as is</li>
<li>librsvg has a minimal support of the edge-cases, which leads to rendering errors</li>
</ul>
</blockquote>
<p>I’m thinking of packaging this for Debian, but I would be interested to know what others think of this.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleHelp the Conservancy raise the remaining $14 0002019-01-09T10:37:00+01:002019-01-09T10:37:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2019-01-09:/2019/01/09/conservancy-fundraiser/<p>The <a href="https://sfconservancy.org/">Software Freedom Conservancy</a> is having the last 7 days to collect the remaining less than $14 000 of the fundraiser generously matched by <a href="https://www.privateinternetaccess.com/">Private Internet Access</a>. All donations up to $90 000 will be matched until 15 January.</p>
<p>Conservancy is an organisation sponsoring nearly 50 free software projects helping …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2019/01/09/conservancy-fundraiser/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>The <a href="https://sfconservancy.org/">Software Freedom Conservancy</a> is having the last 7 days to collect the remaining less than $14 000 of the fundraiser generously matched by <a href="https://www.privateinternetaccess.com/">Private Internet Access</a>. All donations up to $90 000 will be matched until 15 January.</p>
<p>Conservancy is an organisation sponsoring nearly 50 free software projects helping them, most importantly with accounting, paying developers and defending their trademarks and ensuring license compliance.</p>
<p><img alt="Conservancy is currently home to almost fifty member projects" src="https://sfconservancy.org/img/member-project-logos.png"/></p>
<p>Read more about what the Conservancy does on <a href="https://sfconservancy.org/supporter/">their website</a>. The matching funds expire soon, so if you can, please donate directly before 15 January.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articlewpa-supplicant and hostapd 2.7 in Debian2019-01-02T13:29:00+01:002019-01-02T13:29:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2019-01-02:/2019/01/02/wpa-supplicant-2.7/<p>Hostapd and wpa-supplicant 2.7 have been in Debian experimental for some time already, with snapshots available since <a href="https://packages.qa.debian.org/w/wpa/news/20180507T183422Z.html">May 2018</a>, and the official release since <a href="https://packages.qa.debian.org/w/wpa/news/20181203T190858Z.html">3 December 2018</a>. I’ve been using those 2.7 snapshots myself since May, but I do realise my x250 with an Intel Wi-Fi card …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2019/01/02/wpa-supplicant-2.7/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Hostapd and wpa-supplicant 2.7 have been in Debian experimental for some time already, with snapshots available since <a href="https://packages.qa.debian.org/w/wpa/news/20180507T183422Z.html">May 2018</a>, and the official release since <a href="https://packages.qa.debian.org/w/wpa/news/20181203T190858Z.html">3 December 2018</a>. I’ve been using those 2.7 snapshots myself since May, but I do realise my x250 with an Intel Wi-Fi card is probably not the most representative example of hardware wpa-supplicant would often run on, so before I upload 2.7 to unstable, it would be great if more people tested it. So please try to install it <a href="https://packages.debian.org/source/experimental/wpa">from experimental</a> and see if it works for your use cases. In the latest upload, I have enabled a bunch of new upstream features which previously didn’t exist or were still experimental, so it would be great to give them a go.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleBye-bye binary vconfig(1)2019-01-02T13:01:00+01:002019-01-02T13:01:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2019-01-02:/2019/01/02/vlan-vconfig/<p>This morning I have decided that this is the time. The time to finally remove the <a href="https://linux.die.net/man/8/vconfig">binary vconfig utility</a> (which used to <a href="https://blog.sleeplessbeastie.eu/2012/12/23/debian-how-to-create-vlan-interface/">help people configure VLANs</a>) from Debian. But fear not, the command isn’t going anywhere (yet), since almost six years ago I’ve written a <a href="https://bugs.debian.org/501402#39">shell script</a> that …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2019/01/02/vlan-vconfig/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>This morning I have decided that this is the time. The time to finally remove the <a href="https://linux.die.net/man/8/vconfig">binary vconfig utility</a> (which used to <a href="https://blog.sleeplessbeastie.eu/2012/12/23/debian-how-to-create-vlan-interface/">help people configure VLANs</a>) from Debian. But fear not, the command isn’t going anywhere (yet), since almost six years ago I’ve written a <a href="https://bugs.debian.org/501402#39">shell script</a> that replaces it, using <code>ip(8)</code> instead of the old and deprecated API.</p>
<p>If you’re still using vconfig, please give it a test and consider moving to better, newer ways of configuring your VLANs.</p>
<p>If you’re not sure whether you’re using it or not, mostly likely not only you aren’t, but it’s quite possible that you may not even need the <a href="https://tracker.debian.org/pkg/vlan"><code>vlan</code> package</a> that ships vconfig, since the most important functionality of it has since been implemented in ifupdown, networkd and NetworkManager.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleGNU indent 2.2.122018-09-03T13:24:00+02:002018-09-03T13:24:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2018-09-03:/2018/09/03/indent-2.2.12/<p>As the maintainer of <a href="https://www.gnu.org/software/indent/" title="GNU indent homepage">GNU indent</a>, I have just released <a href="https://ftp.gnu.org/gnu/indent/indent-2.2.12.tar.xz" title="indent 2.2.12 tarball">version 2.2.12</a> (<a href="https://ftp.gnu.org/gnu/indent/indent-2.2.12.tar.xz.sig" title="Detached PGP signature">signature</a>), the first release GNU indent saw in eight years.</p>
<p>Highlights include:</p>
<ul>
<li>New options:<ul>
<li><code>-pal</code> / <code>--pointer-align-left and</code>-par<code>/</code>--pointer-align-right`</li>
<li><code>-fnc</code> / <code>--fix-nested-comment</code></li>
<li><code>-gts</code> / <code>--gettext-strings</code></li>
<li><code>-slc</code> / <code>--single-line-conditionals</code></li>
<li><code>-as</code> / <code>--align-with-spaces</code></li>
<li><code>-ut</code> / <code>--use-tabs</code></li>
<li><code>-nut</code> / <code>--no-tabs</code></li>
<li><code>-sar</code> / <code>--spaces-around-initializers</code></li>
<li><code>-ntac</code> / <code>--dont-tab-align-comments</code></li>
</ul>
</li>
<li>C99 …</li><footer><a rel="full-article" class="read-more btn btn-primary" href="/2018/09/03/indent-2.2.12/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></ul><p>As the maintainer of <a href="https://www.gnu.org/software/indent/" title="GNU indent homepage">GNU indent</a>, I have just released <a href="https://ftp.gnu.org/gnu/indent/indent-2.2.12.tar.xz" title="indent 2.2.12 tarball">version 2.2.12</a> (<a href="https://ftp.gnu.org/gnu/indent/indent-2.2.12.tar.xz.sig" title="Detached PGP signature">signature</a>), the first release GNU indent saw in eight years.</p>
<p>Highlights include:</p>
<ul>
<li>New options:<ul>
<li><code>-pal</code> / <code>--pointer-align-left and</code>-par<code>/</code>--pointer-align-right`</li>
<li><code>-fnc</code> / <code>--fix-nested-comment</code></li>
<li><code>-gts</code> / <code>--gettext-strings</code></li>
<li><code>-slc</code> / <code>--single-line-conditionals</code></li>
<li><code>-as</code> / <code>--align-with-spaces</code></li>
<li><code>-ut</code> / <code>--use-tabs</code></li>
<li><code>-nut</code> / <code>--no-tabs</code></li>
<li><code>-sar</code> / <code>--spaces-around-initializers</code></li>
<li><code>-ntac</code> / <code>--dont-tab-align-comments</code></li>
</ul>
</li>
<li>C99 and C11 keywords and <code>typeof</code> are now recognised.</li>
<li><code>-linux</code> preset now includes <code>-nbs</code>.</li>
<li><code>-kr</code> preset now includes <code>-par</code>.</li>
<li>Lots of bug fixes</li>
</ul>
<p>I’d like to thank all of the contributors of this release, most importantly:</p>
<ul>
<li><a href="http://hentenaar.com/">Tim Hentenaar</a> for all of the fixes and refactoring he’s done in his branch</li>
<li><a href="http://xpisar.wz.cz/">Petr Písař</a>, who maintains GNU indent in Red Hat and its derivatives, who’s submitted a lot of fixes and kept supporting users on the mailing list when I couldn’t</li>
<li>Santiago Vila, who maintains GNU indent in Debian</li>
<li>Daniel P. Valentine, who helped me a lot when I initially took over the maintenance of GNU indent</li>
<li>And <a href="https://hg.savannah.gnu.org/hgweb/indent/">lots of others</a> who submitted their patches</li>
</ul>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleLinux Vacation Eastern Europe 20182018-08-22T13:24:00+02:002018-08-22T13:24:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2018-08-22:/2018/08/22/linux-vacation-eastern-europe-2018/<p>On Friday, I will be attending <a href="https://lvee.org/">LVEE</a> (Linux Vacation Eastern Europe) once again after a few years of missing it for various reasons. I will be presenting a talk on my experience of working with <a href="https://validation.linaro.org/">LAVA</a>; the talk is based on a talk given by my colleague <a href="https://gtucker.io/">Guillaume Tucker</a>, who …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2018/08/22/linux-vacation-eastern-europe-2018/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>On Friday, I will be attending <a href="https://lvee.org/">LVEE</a> (Linux Vacation Eastern Europe) once again after a few years of missing it for various reasons. I will be presenting a talk on my experience of working with <a href="https://validation.linaro.org/">LAVA</a>; the talk is based on a talk given by my colleague <a href="https://gtucker.io/">Guillaume Tucker</a>, who helped me a lot when I was ramping up on LAVA.</p>
<p>Since the conference is not well known outside, well, a part of Eastern Europe, I decided I need to write a bit on it. According to the organisers, they had the idea of having a Linux conference after the newly reborn <a href="https://mlug.linux.by/">Minsk Linux User Group</a> organised quite a successful celebration of the ten years anniversary of Debian, and they wanted to have even a bigger event. The first LVEE took place in 2005 in a middle of a forest near <a href="https://en.wikipedia.org/wiki/Hrodna">Hrodna</a>.</p>
<figure>
<img src="/images/posts/lvee2005.jpg"/>
<figcaption>LVEE 2005 group photo</figcaption>
</figure>
<p>As the name suggests, this conference is quite different from many other conferences, and it is actually a bit close in spirit to the <a href="https://linuxbierwanderung.com/about.html">Linux Bier Wanderung</a>. The conference is very informal, it happens basically in a middle of nowhere (until 2010, the Internet connection was very slow and unreliable or absent), and there’s a massive evening programme every evening with beer, <a href="https://en.wikipedia.org/wiki/Shashlyk">shashlyk</a> and a lot of chatting.</p>
<p>My first LVEE was in 2009, and it was, in fact, my first Linux conference. The venue for LVEE has traditionally been a tourist camp in a forest. For those unfamiliar with the concept, a tourist camp (at least in the post-Soviet countries) is an accommodation facility usually providing a bare minimum comfort; people are normally staying in huts or small houses with shared facilities, often located outside.</p>
<p><img alt="Houses part of the tourist camp" class="img-responsive" src="/images/posts/lvee2012-house1.jpg" style="max-width: 80%;"/>
<img alt="Another house part of the tourist camp" class="img-responsive" src="/images/posts/lvee2012-house2.jpg" style="max-width: 80%;"/></p>
<p>When the weather permits (which usually is defined as: <em>not raining</em>), talks are usually held outside. When it starts raining, they move inside one of the houses which is big enough to accommodate most of the people interested in talks.</p>
<p><img alt="Grigory Zlobin in front of a house talks about FOSS in education in Ukraine" class="img-responsive" src="/images/posts/lvee2012-in-talk.jpg" style="max-width: 80%;"/></p>
<p>Some participants prefer to stay in tents:</p>
<p><img alt="Tents of some of the participants" class="img-responsive" src="/images/posts/lvee2012-tents.jpg" style="max-width: 80%;"/></p>
<p>People not interested in talks organise <em>impromptu</em> open-air hacklabs:</p>
<p><img alt="Impromptu open-air hacklab" class="img-responsive" src="/images/posts/lvee2012-hacklab.jpg" style="max-width: 80%;"/></p>
<p>Or take a swim in a lake:</p>
<p><img alt="Person standing on a pier by a lake" class="img-responsive" src="/images/posts/lvee2012-lake.jpg" style="max-width: 80%;"/></p>
<p>Of course, each conference day is followed by shashlyks and beer:</p>
<p><img alt="Shashlyks work in progress" class="img-responsive" src="/images/posts/lvee-winter2018-shashlyk.jpg" style="max-width: 80%;"/></p>
<p>And, on the final day of the conference, cake!</p>
<p><img alt="LVEE cake" class="img-responsive" src="/images/posts/lvee2012-cake.jpg" style="max-width: 80%;"/></p>
<p>This year, for the first time LVEE is being sponsored by <a href="https://collabora.co.uk/">Collabora</a> and Red Hat.</p>
<p>The talks are usually in Russian (with slides usually being in English), but even if you don’t speak Russian and want to attend, fear not: most of the participants speak English to some degree, so you will unlikely feel isolated. If enough English-speaking participants sign up, it is possible that we can organise some aids (e.g. translated subtitles) to make both people not speaking English and not speaking Russian feel at home.</p>
<p>I hope to see some of the readers at LVEE next time :)</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleUpcoming git-crecord release2018-07-13T13:10:00+02:002018-07-13T13:10:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2018-07-13:/2018/07/13/upcoming-git-crecord-release/<p>More than 1½ years since the first release of <a href="https://github.com/andrewshadura/git-crecord">git-crecord</a>, I’m preparing a big update. Not aware how exactly many people are using it, I neglected the maintenance for some time, but last month I’ve decided I need to take action and fix some issues I’ve known …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2018/07/13/upcoming-git-crecord-release/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>More than 1½ years since the first release of <a href="https://github.com/andrewshadura/git-crecord">git-crecord</a>, I’m preparing a big update. Not aware how exactly many people are using it, I neglected the maintenance for some time, but last month I’ve decided I need to take action and fix some issues I’ve known since the first release.</p>
<p>First of all, I’ve fixed a few minor issues with <code>setup.py</code>-based installer some users reported.</p>
<p>Second, I’ve ported a batch of updates from a another crecord derivative merged into Mercurial. That also brought some updates to the bits of Mercurial code git-crecord is using.</p>
<p>Third, long waited Python 3 support is here. I’m afraid at the moment I cannot guarantee support of patches in encodings other than the locale’s one, but if that turns out to be a needed feature, I can think about implementing it.</p>
<p>Fourth, missing staging and unstaging functionality is being implemented, subject to the availability of free time during the holiday :)</p>
<p>The project is currently hosted at GitHub: <a href="https://github.com/andrewshadura/git-crecord">https://github.com/andrewshadura/git-crecord</a>.</p>
<p>P.S. In case you’d like to support me hacking on git-crecord, or any other of my free software activities, you can tip my <a href="https://www.patreon.com/andrewsh">Patreon account</a>.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleWorking in open source: part 12018-06-15T16:08:00+02:002018-06-15T16:08:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2018-06-15:/2018/06/15/working-in-open-source-part-1/<p>Three years ago on this day I joined <a class="reference external" href="https://www.collabora.com/">Collabora</a> to work on free software full-time. It still feels a bit like yesterday, despite so much time passing since then. In this post, I’m going to reconstruct the events of that year.</p>
<p>Back in 2015, I worked for Alcatel-Lucent, who …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2018/06/15/working-in-open-source-part-1/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Three years ago on this day I joined <a class="reference external" href="https://www.collabora.com/">Collabora</a> to work on free software full-time. It still feels a bit like yesterday, despite so much time passing since then. In this post, I’m going to reconstruct the events of that year.</p>
<p>Back in 2015, I worked for Alcatel-Lucent, who had a branch in Bratislava. I can’t say I didn’t like my job — quite contrary, I found it quite exciting: I worked with mobile technologies such as 3G and LTE, I had really knowledgeable and smart colleagues, and it was the first ‘real’ job (not counting the small business my father and I ran) where using Linux for development was not only not frowned upon, but was a mandatory part of the standard workflow, and running it on your workstation was common too, even though not official.</p>
<p>However, after working for Alcatel-Lucent for a year, I found I don’t like some of the things about this job. We developed proprietary software for the routers and gateways the company produced, and despite the fact we used quite a lot of open source libraries and free software tools, we very rarely contributed anything back, and if this happened at all, it usually happened unofficially and not on the company’s time. Each time I tried to suggest we need to upstream our local changes so that we don’t have to maintain three different patchsets for different upstream versions ourselves, I was told I know nothing about how the business works, and that doing that would give up the control on the code, and we can’t do that. At the same time, we had no issue incorporating permissively-licensed free software code. The more I worked at Alcatel-Lucent, the more I felt I am just getting useless knowledge of a proprietary product I will never be able to reuse once and if I leave the company. At some point, in a discussion at work someone said that doing software development (including my free software work) even on my free time may constitute a conflict of interests, and the company may be unhappy about it. Add to that that despite relatively flexible hours, working from home was almost never allowed, as was working from other offices of the company.</p>
<p>These were the major reasons I quit my job at Alcatel-Lucent, and my last day was 10 April 2018. Luckily, we reached an agreement that I will still get my normal pay while on the notice period despite not actually going to the office or doing any work, which allowed me to enjoy two months of working on my hobby projects while not having to worry about money.</p>
<p>To be honest, I don’t want to seem like I quit my job just because it was all proprietary software, and I did plan to live from donations or something, it wasn’t quite like that. While still working for Alcatel-Lucent, I was offered a job which was developing real-time software running <em>inside</em> the Linux kernel. While I have declined this job offer, mostly because it was a small company with less than a dozen employees, and I would need to take over the responsibility for a huge piece of code — which was, in fact, also proprietary, this job offer taught me this thing: there were jobs out there where my knowledge of Linux was of an actual use, even in the city I lived in. The other thing I learnt was this: there were remote Linux jobs too, but I needed to become self-employed to be able to take them, since my immigration status at the moment didn’t allow me to be employed abroad.</p>
<div class="figure">
<img alt="Picture of the business license. Text in Slovak: ‘Osvedčenie o živnostenskom opravnení. Andrei Shadura’." class="img-responsive" src="/images/posts/business-license.jpg"/>
<p class="caption">The business license I received within a few days of quitting my job</p>
</div>
<p>Feeling free as a bird, having the business registered, I’ve spent two months hacking, relaxing, travelling to places in Slovakia and Ukraine, and thinking about how am I going to earn money when my two months vacation ends.</p>
<div class="figure">
<img alt="A street in Trenčín; the castle can be seen above the building’s roof." class="img-responsive" src="/images/posts/trencin.jpg"/>
<p class="caption">In Trenčín</p>
</div>
<p>The obvious idea was to consult, but that wouldn’t guarantee me constant income. I could consult on Debian or Linux in general, or on version control systems — in 2015 I was an active member of the <a class="reference external" href="https://kallithea-scm.org/">Kallithea project</a> and I believed I could help companies migrate from CVS and Subversion to Mercurial and Git hosted internally on Kallithea. (I’ve actually also got a job offer from Unity Technologies to hack on Kallithea and related tools, but I had to decline it since it would require moving to Copenhagen, which I wasn’t ready for, despite liking the place when I visited them in May 2015.)</p>
<p>Another obvious idea was working for Red Hat, but knowing how slow their HR department was, I didn’t put too much hope into it. Besides, when I contacted them, they said they need to get an approval for me to work for them remotely and as a self-employed, lowering my chances on getting a job there without having to relocate to Brno or elsewhere.</p>
<p>At some point, reading Debian Planet, I found <a class="reference external" href="http://smcv.pseudorandom.co.uk/2015/why_polkit/">a blog post by Simon McVittie</a> on polkit, in which he mentioned Collabora. Soon, I applied, had my interviews and a job offer.</p>
<p><em>To be continued later…</em></p>
http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articlePorting inputplug to XCB2018-05-20T21:50:00+02:002018-05-20T21:50:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2018-05-20:/2018/05/20/porting-inputplug-from-xlib-to-xcb/<p>5 years ago I wrote <a href="https://bitbucket.org/andrew_shadura/inputplug">inputplug</a>, a tiny
daemon which connects to your X server and monitors its input devices, running an external
command each time a device is connected or disconnected.</p>
<p>I have used a custom keyboard layout and a fairly non-standard settings for my pointing
devices since 2012 …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2018/05/20/porting-inputplug-from-xlib-to-xcb/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>5 years ago I wrote <a href="https://bitbucket.org/andrew_shadura/inputplug">inputplug</a>, a tiny
daemon which connects to your X server and monitors its input devices, running an external
command each time a device is connected or disconnected.</p>
<p>I have used a custom keyboard layout and a fairly non-standard settings for my pointing
devices since 2012. I always annoyed me those settings would be re-set every time the device
was disconnected and reconnected again, for example, when the laptop was brought back up from
the suspend mode. I usually solved that by putting commands to reconfigure my input settings
into the resume hook scripts, but that obviously didn’t solve the case of connecting external
keyboards and mice. At some point those hook scripts stopped to work because they would run too
early when the keyboard and mice were not they yet, so I decided to write inputplug.</p>
<p>Inputplug was the first program I ever wrote which used X at a low level, and I had to use
Xlib to access the low-level features I needed. More specifically, inputplug uses XInput
X extension and listens to <code>XIHierarchyChanged</code> events. In June 2014, Vincent Bernat
<a href="https://bitbucket.org/andrew_shadura/inputplug/commits/87bea9b7f8766c109b1ec89b78778677fc70ab23">contributed</a>
a patch to rely on XInput2 only.</p>
<p>During the <a href="https://wiki.debian.org/DebianEvents/de/2018/MiniDebConfHamburg">MiniDebCamp</a>, I had a
typical case of yak shaving despite not having any yaks around: I wanted to migrate inputplug’s
packaging from Alioth to Salsa, and I had an idea to update the package itself as well. I had
an idea of adding optional systemd user session integration, and the easiest way to do that
would be to have inputplug register a D-Bus service. However, if I just registered the service,
introspecting it would cause annoying delays since it wouldn’t respond to any of the messages
the clients would send to it. Handling messages would require me to integrate polling into the
event loop, and it turned out it’s not easy to do while sticking to Xlib, so I decided to try
and port inputplug to XCB.</p>
<p>For those unfamiliar with XCB, here’s a bit of background: XCB is a library which implements
the X11 protocol and operates on a slightly lower level than Xlib. Unlike Xlib, it only works
with structures which map directly to the wire protocol. The functions XCB provides are really
atomic: in Xlib, it not unusual for a function to perform multiple X transactions or to juggle
the elements of the structures a bit. In XCB, most of the functions are relatively thin wrappers
to enable packing and unpacking of the data. Let me give you an example.</p>
<p>In Xlib, if you wanted to check whether the X server supports a specific extension, you would write
something like this:</p>
<div class="highlight"><pre><span></span><code><span class="n">XQueryExtension</span><span class="p">(</span><span class="n">display</span><span class="p">,</span><span class="w"> </span><span class="s">"XInputExtension"</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">xi_opcode</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">event</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">error</span><span class="p">)</span>
</code></pre></div>
<p>Internally, <code>XQueryExtension</code> would send a QueryExtension request to the X server, wait
for a reply, parse the reply and return the major opcode, the first event code and the
first error code.</p>
<p>With XCB, you need to separately send the request, receive the reply and fetch the data you need
from the structure you get:</p>
<div class="highlight"><pre><span></span><code><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">ext</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"XInputExtension"</span><span class="p">;</span>
<span class="n">xcb_query_extension_cookie_t</span><span class="w"> </span><span class="n">qe_cookie</span><span class="p">;</span>
<span class="n">qe_cookie</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">xcb_query_extension</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span><span class="w"> </span><span class="n">strlen</span><span class="p">(</span><span class="n">ext</span><span class="p">),</span><span class="w"> </span><span class="n">ext</span><span class="p">);</span>
<span class="n">xcb_query_extension_reply_t</span><span class="w"> </span><span class="o">*</span><span class="n">rep</span><span class="p">;</span>
<span class="n">rep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">xcb_query_extension_reply</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span><span class="w"> </span><span class="n">qe_cookie</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">);</span>
</code></pre></div>
<p>At this point, <code>rep</code> has its field <code>preset</code> set to <code>true</code> if the extension is present. The rest
of the things are in the structure as well, which you have to <code>free</code> yourself after the use.</p>
<p>Things get a bit more tricky with requests returning arrays, like <code>XIQueryDevice</code>. Since the
<code>xcb_input_xi_query_device_reply_t</code> structure is difficult to parse manually, XCB provides an
iterator, <code>xcb_input_xi_device_info_iterator_t</code> which you can use to iterate over the structure:
<code>xcb_input_xi_device_info_next</code> does the necessary parsing and moves the pointer so that each
time it is run the iterator points to the next element.</p>
<p>Since replies in the X protocol can have variable-length elements, e.g. device names, XCB also
provides wrappers to make accessing them easier, like <code>xcb_input_xi_device_info_name</code>.</p>
<p>Most of the code of XCB is generated: there is an XML description of the X protocol which is used
in the build process, and the C code to parse and generate the X protocol packets is generated each
time the library is built. This means, unfortunately, that the <a href="https://xcb.freedesktop.org/manual/">documentation</a>
is quite useless, and there aren’t many examples online, especially if you’re going to use rarely
used functions like XInput hierarchy change events.</p>
<p>I decided to do the porting the hard way, changing Xlib calls to XCB calls one by one, but there’s an
<a href="https://xcb.freedesktop.org/MixingCalls/">easier way</a>: since Xlib is now actually <em>based on XCB</em>, you can <code>#include <X11/Xlib-xcb.h></code> and use
<code>XGetXCBConnection</code> to get an XCB connection object corresponding to the Xlib’s <code>Display</code> object.
Doing that means there will still be a single X connection, and you will be able to mix Xlib and
XCB calls.</p>
<p>When porting, it often is useful to have a look at the sources of Xlib: it becomes obvious what XCB functions
to use when you know what Xlib does internally (thanks to Mike Gabriel for pointing this out!).</p>
<p>Another thing to remember is that the constants and enums Xlib and XCB define usually have the same values
(mandated by the X protocol) despite having slightly different names, so you can mix them too. For example,
since inputplug passes the XInput event names to the command it runs, I decided to keep the names as Xlib
defines them, and since I’m creating the corresponding strings by using a C preprocessor macro, it was easier
for me to keep using <code>XInput2.h</code> instead of defining those strings by hand.</p>
<p>If you’re interested in the result of this porting effort, have a look at <a href="https://bitbucket.org/andrew_shadura/inputplug/commits/d51dad6b9736813fe9e0612b38db43b623c9a335">the code in the Mercurial repo</a>. Unfortunately, it cannot be packaged for Debian yet since the
Debian package for XCB doesn’t ship the module for XInput (see bug #<a href="https://bugs.debian.org/733227">733227</a>).</p>
<p>P.S. Thanks again to Mike Gabriel for providing me important help — and explaining where to look for more of it ;)</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleGoodbye Octopress, hello Pelican2018-05-18T22:05:00+02:002018-05-18T22:05:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2018-05-18:/2018/05/18/goodbye-octopress/<p><img class="img-responsive" src="/images/posts/minidebconf-hamburg.jpg" style="max-width: 60%;"></p>
<p>Hi from MiniDebConf in Hamburg!</p>
<p>As you may have noticed, I don’t update this blog often. One of the reasons why this was
happening was that until now it was incredibly difficult to write posts. The software I
used, Octopress (based on Jekyll) was based on Ruby, and it …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2018/05/18/goodbye-octopress/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p><img class="img-responsive" src="/images/posts/minidebconf-hamburg.jpg" style="max-width: 60%;"/></p>
<p>Hi from MiniDebConf in Hamburg!</p>
<p>As you may have noticed, I don’t update this blog often. One of the reasons why this was
happening was that until now it was incredibly difficult to write posts. The software I
used, Octopress (based on Jekyll) was based on Ruby, and it required quite specific versions
of its dependencies. I had the workspace deployed on one of my old laptops, but when I attempted
to reproduce it on the laptop I currently use, I failed to. Some dependencies could not be installed,
others failed, and my Ruby skills weren’t enough to fix that mess. (I have to admit my Ruby skills
improved <em>insignificantly</em> since the time I installed Octopress, but that wasn’t enough to help in
this case.)</p>
<p>I’ve spent some time during this DebCamp to migrate to Pelican, which is written in Python, packaged
in Debian, and its dependencies are quite straighforward to install. I had to install (and write) a few
plugins to make the migration easier, and port my custom Octopress Bootstrap theme to Pelican.</p>
<p>I no longer include any scripts from Twitter or Facebook (I made <em>Tweet</em> and <em>Share</em> button static links),
and the Disqus comments are loaded only on demand, so reading this blog will respect your privacy better
than before.</p>
<p>See you at MiniDebConf tomorrow!</p>
<p><img class="img-responsive" src="/images/posts/minidebconf-hamburg-debian.jpg" style="max-width: 60%;"/></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleSay no to Slack, say yes to Matrix2018-03-10T14:50:00+01:002018-03-10T14:50:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2018-03-10:/2018/03/10/say-no-to-slack/<p>Of all proprietary chatting systems, Slack has always seemed one of the worst to me. Not only it’s
a closed proprietary system with no sane clients, open source or not, but it not just one walled garden,
as Facebook or WhatsApp are, but a constellation of walled gardens, isolated …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2018/03/10/say-no-to-slack/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Of all proprietary chatting systems, Slack has always seemed one of the worst to me. Not only it’s
a closed proprietary system with no sane clients, open source or not, but it not just one walled garden,
as Facebook or WhatsApp are, but a constellation of walled gardens, isolated from each other. To be able
to participate in multiple Slack communities, the user has to create multiple accounts and keep multiple
chat windows open all the time. Federation? Self-hosting? Owning your data? All of those are not a thing
in Slack. Until recently, it was possible to at least keep the logs of all conversations locally by connecting
to the chat using IRC or XMPP if the gateway was enabled.</p>
<p>Now, with <a href="https://www.theregister.co.uk/2018/03/09/slack_cuts_ties_to_irc_and_xmpp/">Slack shutting down gateways</a> not only
you cannot keep the logs on your computer, you also cannot use a client of your choice to connect to Slack. They also began
<a href="https://api.slack.com/changelog/2017-09-the-one-about-usernames">changing the bots API</a> which was likely the reason
the <a href="https://github.com/matrix-org/matrix-appservice-slack/issues/65">Matrix-to-Slack gateway didn’t work properly at times</a>.
The issue has since resolved itself, but Slack doesn’t give any guarantees the gateway will continue working, and obviously
they aren’t really interested in keeping it working.</p>
<p>So, following <a href="http://gwolf.org/node/4119/">Gunnar Wolf’s advice</a> (consider also reading <a href="https://link.springer.com/chapter/10.1007/978-3-319-57735-7_1">this article by Megan Squire</a>), I recommend you stop using Slack. If you prefer an isolated
chat system with features Slack provides, and you can self-host, consider <a href="https://about.mattermost.com/">Mattermost</a> or
<a href="https://rocket.chat/">Rocket.Chat</a>. Both seem to provide more or less the same features as Slack, but don’t lock you in, and
you can choose to either use their paid cloud offering, or run it on your own server. We’ve been using Mattermost at Collabora
since July last year, and while it’s not perfect, it’s not a bad piece of software.</p>
<p>If you woulde prefer a system you can federate, you may be interested to have a look at <a href="https://matrix.org/">Matrix</a>. Matrix is
an open decentralised protocol and ecosystem, which architecturally looks similar to XMPP, but uses different technologies and
offers a richer and more modern baseline, including VoIP, end-to-end encryption, decentralised history and content storage, easy
bot integration and more. The web client for Matrix, <a href="https://riot.im/">Riot</a> is comparable to Slack, but unlike Slack, there are
<a href="https://matrix.org/docs/projects/try-matrix-now.html">more clients</a> you can use, including Weechat, libpurple, a bunch of Qt-based
clients and, importantly, Riot for Android and iOS.</p>
<p>You don’t have to self-host a Matrix homeserver, since Matrix.org runs one you can use, but it’s quite easy to run one if you decide
to, and you don’t even have to migrate your existing chats — you just join them from accounts on your own homeserver, and that’s it!</p>
<p>To help you with the decision to move from Slack to Matrix, you should know that
since Matrix has a Slack gateway, you can gradually migrate your colleagues to the new infrastructure, by joining the Slack and Matrix chats
together, and dropping the gateway only when everyone moves from Slack.</p>
<p>Repeating Gunnar, <em>say no to predatory tactics. Say no to Embrace, Extend and Extinguish. Say no to Slack.</em></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleHow to stop gnome-settings-daemon messing with keyboard layouts2018-02-23T16:23:00+01:002018-02-23T16:23:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2018-02-23:/2018/02/23/gnome-settings-daemon-keyboard-layouts/<p>In case you, just like me, want to have a heavily customised keyboard layout configuration, possibly with different layouts on different input devices (I recommend <a href="https://bitbucket.org/andrew_shadura/inputplug/">inputplug</a> to make that work), you probably don’t want your desktop environment to mess with your settings or, worse, re-set them to some default …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2018/02/23/gnome-settings-daemon-keyboard-layouts/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>In case you, just like me, want to have a heavily customised keyboard layout configuration, possibly with different layouts on different input devices (I recommend <a href="https://bitbucket.org/andrew_shadura/inputplug/">inputplug</a> to make that work), you probably don’t want your desktop environment to mess with your settings or, worse, re-set them to some default from time to time. Unfortunately, that’s exactly what <code>gnome-settings-daemon</code> does by default in GNOME and Unity. While I could modify inputplug to detect that and undo the changes immediately, it turned out this behaviour can be disabled with an underdocumented option:</p>
<div class="highlight"><pre><span></span><code>gsettings set org.gnome.settings-daemon.plugins.keyboard active false
</code></pre></div>
<p>Thanks to <a href="https://blogs.gnome.org/seb128/">Sebastien Bacher</a> for helping me with this two years ago.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleManual control of OpenEmbedded -dbg packages2016-09-06T14:28:00+02:002016-09-06T14:28:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2016-09-06:/2016/09/06/manual-control-of-dbg-packages/<p>In December last year, OpenEmbebbed <a href="http://lists.openembedded.org/pipermail/openembedded-core/2015-December/114162.html">introduced automatic debug packages</a>. Prior to that, you’d need to manually construct <code>FILES_${PN}-dbg</code> variable in your recipe. If you need to retain manual control over precisely what does into debug packages, set an undocumented <code>NOAUTOPACKAGEDEBUG</code> variable to <code>1</code>, the same way Qt …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2016/09/06/manual-control-of-dbg-packages/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>In December last year, OpenEmbebbed <a href="http://lists.openembedded.org/pipermail/openembedded-core/2015-December/114162.html">introduced automatic debug packages</a>. Prior to that, you’d need to manually construct <code>FILES_${PN}-dbg</code> variable in your recipe. If you need to retain manual control over precisely what does into debug packages, set an undocumented <code>NOAUTOPACKAGEDEBUG</code> variable to <code>1</code>, the same way Qt recipe does:</p>
<div class="highlight"><pre><span></span><code>NOAUTOPACKAGEDEBUG<span class="w"> </span>=<span class="w"> </span>"1"
FILES_<span class="cp">${</span><span class="n">PN</span><span class="cp">}</span>-dev<span class="w"> </span>=<span class="w"> </span>"<span class="cp">${</span><span class="n">includedir</span><span class="cp">}</span>/<span class="cp">${</span><span class="n">QT_DIR_NAME</span><span class="cp">}</span>/Qt/*"
FILES_<span class="cp">${</span><span class="n">PN</span><span class="cp">}</span>-dbg<span class="w"> </span>=<span class="w"> </span>"/usr/src/debug/"
FILES_<span class="cp">${</span><span class="n">QT_BASE_NAME</span><span class="cp">}</span>-demos-doc<span class="w"> </span>=<span class="w"> </span>"<span class="cp">${</span><span class="n">docdir</span><span class="cp">}</span>/<span class="cp">${</span><span class="n">QT_DIR_NAME</span><span class="cp">}</span>/qch/qt.qch"
</code></pre></div>
<p>P.S. Knowing this would have saved me and my colleagues days of work.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleMigrate to systemd without a reboot2016-06-15T13:51:00+02:002016-06-15T13:51:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2016-06-15:/2016/06/15/migrate-to-systemd-without-a-reboot/<p>Yesterday I was fixing <a href="https://bitbucket.org/conservancy/kallithea/pull-requests/235/minor-changes/diff#comment-19707125">an issue</a> with one of the servers behind <a href="https://kallithea-scm.org">kallithea-scm.org</a>: the hook intended to propagage pushes from Our Own Kallithea to Bitbucket stopped working. Until yesterday, that server was using Debian’s flavour of System V init and djb’s dæmontools to keep things running. To …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2016/06/15/migrate-to-systemd-without-a-reboot/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Yesterday I was fixing <a href="https://bitbucket.org/conservancy/kallithea/pull-requests/235/minor-changes/diff#comment-19707125">an issue</a> with one of the servers behind <a href="https://kallithea-scm.org">kallithea-scm.org</a>: the hook intended to propagage pushes from Our Own Kallithea to Bitbucket stopped working. Until yesterday, that server was using Debian’s flavour of System V init and djb’s dæmontools to keep things running. To make the hook asynchronous, I wrote a service to be managed to dæmontools, so that concurrency issued would be solved by it. However, I didn't implement any timeouts, so when last week <code>wget</code> froze while pulling Weblate's hook, there was nothing to interrupt it, so the hook stopped working since dæmontools thought it's already running and wouldn’t re-trigger it. Killing <code>wget</code> helped, but I decided I need to do something with it to prevent the situation from happening in the future.</p>
<p>I’ve been using systemd at <a href="https://collabora.co.uk/">work</a> for the last year, so I am now confident I'm happier with systemd than with dæmontools, so I decided to switch the server to systemd. Not surprisingly, I prepared unit files in about 5 minutes without having to look into the manuals again, while with dæmontools I had to check things every time I needed to change something. The tricky thing was the switch itself. It is a virtual server, presumably running in Xen, and I don’t have access to the console, so if I <s>bork</s> break something, I need to summon Bradley Kuhn or someone from <a href="https://sfconservancy.org/">Conservancy</a>, who’s kindly donated the server to the project. In any case, I decided to attempt to upgrade without a reboot, so that I have more options to roll back my changes in the case things go wrong.</p>
<p>After studying the manpages of both systemd’s <code>init</code> and sysvinit’s <code>init</code>, I realised I can install systemd as <code>/sbin/init</code> and ask already running System V init to re-exec. However, systemd’s <code>init</code> can’t talk to System V init, so before installing systemd I made a backup on it. It’s also important to stop all running services (except probably ssh) to make sure systemd doesn’t start second instances of each. And then: <code>/tmp/init u</code> — and we’re running systemd! A couple of additional checks, and it’s safe to reboot.</p>
<p>Only when I did all that I realised that in the case of systemd not working I’d probably not be able to undo my changes if my connection interrupted. So, even though at the end it worked, probably it’s not a good idea to perform such manipulations when you don’t have an alternative way to connect to the server :)</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articlePhulud? No, Phulad.2016-02-26T17:45:00+01:002016-02-26T17:45:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2016-02-26:/2016/02/26/phulad/<p>If you bought an North India travel guide by Vanessa Betts and Victoria
McCulloch, and tried to figure out where is ‘Phulud’ and how to get there
from Deogarh (and how to get to Deogarh itself from Udaipur), don’t waste your
time googling, as <strong>it’s not Phulud, but …</strong><footer><a rel="full-article" class="read-more btn btn-primary" href="/2016/02/26/phulad/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>If you bought an North India travel guide by Vanessa Betts and Victoria
McCulloch, and tried to figure out where is ‘Phulud’ and how to get there
from Deogarh (and how to get to Deogarh itself from Udaipur), don’t waste your
time googling, as <strong>it’s not Phulud, but <a href="https://en.wikipedia.org/wiki/Phulad">Phulad</a>.</strong></p>
<p>It does seem that the narrow gauge journey from Deogarh to Phulad is indeed beautiful:</p>
<iframe allowfullscreen="" frameborder="0" height="480" src="https://www.youtube.com/embed/_BXKMRxieGA" width="853"></iframe>
<p>Meanwhile, I have also found this very interesting post by Mary Anne Erickson: <a href="http://www.huffingtonpost.com/mary-anne-erickson/impressions-of-india-udai_b_6827462.html">Impressions of India: Udaipur to Deogarh</a>. I’m not yet sure we’re going to follow that route, but it seems promising.</p>
<p>P.S. Despite what the guide said about the airport in Jaisalmer, which is <em>due to open in 2013</em>, according to the reports, it is <a href="https://en.wikipedia.org/wiki/Jaisalmer_Airport">still</a> <a href="http://www.businessinsider.com/take-a-look-inside-indias-brand-new-ghost-airport-2015-8">not open</a>, so we have to skip that city. Oh well.</p>
<p><strong>EDIT</strong>: The guide actually also says, on page 10: <em>Fly from Jaisalmer back to Delhi to connect with your flight home.</em> Fact checking? No, who needs that? :)</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleCommunity time at Collabora2016-02-06T18:22:00+01:002016-02-06T18:22:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2016-02-06:/2016/02/06/community-time-at-collabora/<p>I haven't yet blogged about this (as normally I don't blog often), but I
joined <a href="https://www.collabora.com/">Collabora</a> in June last year. Since then,
I had an opportunity to work with OpenEmbedded again, write a kernel patch,
learn lots of things about systemd (in particular, how to stop worrying about
it taking …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2016/02/06/community-time-at-collabora/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>I haven't yet blogged about this (as normally I don't blog often), but I
joined <a href="https://www.collabora.com/">Collabora</a> in June last year. Since then,
I had an opportunity to work with OpenEmbedded again, write a kernel patch,
learn lots of things about systemd (in particular, how to stop worrying about
it taking over the world and so on), and do lots of other things.</p>
<p>As one would expect when working for a free software consultancy, our customers
do understand the value of the community and contributing back to it, and so does the
customer for the project I'm working on. In fact, our customer
insists we keep the number of locally applied patches to, for example, Linux kernel, to
minimum, submitting as much as possible upstream.</p>
<p>However, apart from the upstreaming work which may be done for the customer, Collabora
encourages us, the engineers, to spend up to two hours weekly for upstreaming on top
of what customers need, and up to five days yearly as paid Community days. These
community days may be spent working on the code or doing volunteering at free software
events or even speaking at conferences.</p>
<p>Even though on this project I <a href="https://anonscm.debian.org/cgit/collab-maint/ifupdown.git/commit/?id=da5ff47d42c094a913c01fbb27f7b9be60538d15">have</a>
<a href="https://anonscm.debian.org/cgit/collab-maint/ifupdown.git/commit/?id=05ba6bf079516550eeea15210f39a82bbfb03cae">already</a>
<a href="https://anonscm.debian.org/cgit/collab-maint/ifupdown.git/commit/?id=86c01dc85ae3042ad0ccc019dc10ffef3fbf6f74">been</a>
<a href="https://anonscm.debian.org/cgit/collab-maint/ifupdown.git/commit/?id=ba122e2c102fc4cdedac0dd2dd3695705c5f42ad">paid</a>
for contributing to the free software project which I maintained in my free time previously (ifupdown),
paid community time is a great opportunity to contribute to the projects I'm interested in, and if
the projects I'm interested in coincide with the projects I'm working with, I effectively can spend even
more time on them.</p>
<p>A bit unfortunately for me, I haven't spent enough time last year to plan my community days, so I used most
of them in the last weeks of the calendar year, and I used them <ins datetime="2016-02-06T20:49:00+01:00">(and some of my upstreaming hours)</ins> on something that benefitted both free software
community and Collabora. I'm talking about <a href="http://sparkleshare.org/">SparkleShare</a>, a cross-platform Git-based
file synchronisation solution written in C#. SparkleShare provides an easy to use interface for Git, or, actually,
it makes it possible to not use any Git interface at all, as it monitors the working directory using inotify and
commits stuff right after it changes. It automatically handles conflicts even for binary files, even though I
have to admit its handling could still be improved.</p>
<p><img src="/images/posts/sparkles.png" style="float: right;"/></p>
<p>At Collabora, we use SparkleShare to store all sorts of internal documents, and it's being used by users not
familiar with command line interfaces too. Unfortunately, the version we <a href="https://packages.qa.debian.org/s/sparkleshare/news/20151221T223515Z.html">recently had</a>
in Debian had a couple of very annoying bugs, making it a great pain to use it: it would not notice edits in
local files, or not notice new commits being pushed to the server, and that led to individual users' edits
being lost sometimes. Not cool, especially when the document has to be sent to the customer in a couple of
minutes.</p>
<p>The new versions, 1.4 (and recently released 1.5) was reported as being much better and also fixing some crashes,
but it also used GTK+ 3 and some libraries not yet packaged for Debian. <a href="https://launchpad.net/~rebuntu16">Thanh Tung Nguyen</a>
packaged these packages (and a newer SparkleShare) for Ubuntu and published them in his <a href="https://launchpad.net/~rebuntu16/+archive/ubuntu/sparkleshare+unofficial">PPA</a>, but they required some work to be fit for Debian.</p>
<p>I have never touched Mono packages before in my life, so I had to
learn a lot. Some time was spent talking to upstream about fixing
their copyright statements (they had none in the code, and only
one author was mentioned in configure.ac, and nowhere else in the
source), a bit more time went into adjusting and updating the patches
to the current source code version. Then, of course, waiting the
packages to go through NEW. Fixing <a href="http://bugs.debian.org/810280">parallel build issues</a>,
waiting for buildds to all build dependencies for at least one architecture…
But then, finally, on 19<sup>th</sup> of January I had the <a href="https://packages.qa.debian.org/s/sparkleshare/news/20160119T093826Z.html">updated SparkleShare</a>
in Debian.</p>
<p>As you may have already guessed, this blog post has been sponsored by
Collabora, the first of my employers to <del datetime="2016-02-06T20:49:00+01:00">encourage</del> require me to work on
free software in my paid time :)</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articlePublic transport map of Managua2016-01-10T17:26:00+01:002016-01-10T17:26:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2016-01-10:/2016/01/10/public-transport-map-of-managua/<p>Holger Levsen <a href="http://layer-acht.org/thinking/blog/20160110-support-mapanica-net/">writes</a> about the public transport map of Managua, Nicaragua, which is, according to him, the first detailed map of Managua's bus network:</p>
<blockquote>
<p>If you haven't been to Managua, you might not be able to immediatly appreciate the usefulness of this. Up until now, there has been no map …</p><footer><a rel="full-article" class="read-more btn btn-primary" href="/2016/01/10/public-transport-map-of-managua/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></blockquote><p>Holger Levsen <a href="http://layer-acht.org/thinking/blog/20160110-support-mapanica-net/">writes</a> about the public transport map of Managua, Nicaragua, which is, according to him, the first detailed map of Managua's bus network:</p>
<blockquote>
<p>If you haven't been to Managua, you might not be able to immediatly appreciate the usefulness of this. Up until now, there has been no map nor timetable for the bus system, which as you can see now easily and from far away, is actually quite big and is used by 80% of the population in a city, where the streets still have no names.</p>
</blockquote>
<p>Having had a look at the map they produced, I have to admit I quite liked it:
<img alt="MapaNica.net, Rutas de Managua y Ciudad Sandino" src="/images/posts/9raAoVT.png"/></p>
<p>MapaNica, the community behind said map, are raising funds to make lives of locals easier by publishing a printed version of the map and distributing it. They have already raised more than $3300 of their $7500 goal. Every further donation will help them print more maps.</p>
<p>Please go to <a href="http://support.mapanica.net/">support.mapanica.net</a> and support their initiative!</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleSupport Software Freedom Conservancy2015-11-30T19:26:00+01:002015-11-30T19:26:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2015-11-30:/2015/11/30/support-software-freedom-conservancy/<p>The <a href="https://sfconservancy.org/">Software Freedom Conservancy</a> are desperately looking for financial support after one of their corporate supporters have stopped their sponsorship. This week, there's an anonymous pledge to match donations from new supporters.</p>
<p>Becoming an SFC supporter will help them fight for our software freedom. I have signed up for a …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2015/11/30/support-software-freedom-conservancy/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>The <a href="https://sfconservancy.org/">Software Freedom Conservancy</a> are desperately looking for financial support after one of their corporate supporters have stopped their sponsorship. This week, there's an anonymous pledge to match donations from new supporters.</p>
<p>Becoming an SFC supporter will help them fight for our software freedom. I have signed up for a monthly donation, and I suggest you do so too <a href="https://sfconservancy.org/supporter/">here</a>.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articlePower button and logind2015-04-16T14:05:00+02:002015-04-16T14:05:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2015-04-16:/2015/04/16/power-button-and-logind/<p>If you have configured your laptop's power button to act as sleep button using <code>acpid</code>, then installed systemd or systemd-shim and pressed the button only to find your laptop to shut down after it wakes up from sleep, set these options in <code>/etc/systemd/logind.conf</code>:</p>
<pre>[Login]
HandlePowerKey=ignore
HandleSuspendKey …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2015/04/16/power-button-and-logind/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></pre><p>If you have configured your laptop's power button to act as sleep button using <code>acpid</code>, then installed systemd or systemd-shim and pressed the button only to find your laptop to shut down after it wakes up from sleep, set these options in <code>/etc/systemd/logind.conf</code>:</p>
<pre>[Login]
HandlePowerKey=ignore
HandleSuspendKey=ignore
HandleHibernateKey=ignore
HandleLidSwitch=ignore</pre>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleUI translation tools and version control2015-04-13T15:59:00+02:002015-04-13T15:59:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2015-04-13:/2015/04/13/gtranslator-as-a-ui-translation-tool-no-thanks/<p>Today I decided to try some translation tools I could install on my laptop locally
to translate <a href="https://kallithea-scm.org/">Kallithea</a>, so I'd not need to be on-line
to use Michal Čihař's wonderful <a href="https://weblate.org/">Weblate</a>.</p>
<p>The first tool I tried was <a href="https://wiki.gnome.org/Apps/Gtranslator">Gtranslator</a>. I edited about 5 strings, and then wanted
to commit my changes …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2015/04/13/gtranslator-as-a-ui-translation-tool-no-thanks/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Today I decided to try some translation tools I could install on my laptop locally
to translate <a href="https://kallithea-scm.org/">Kallithea</a>, so I'd not need to be on-line
to use Michal Čihař's wonderful <a href="https://weblate.org/">Weblate</a>.</p>
<p>The first tool I tried was <a href="https://wiki.gnome.org/Apps/Gtranslator">Gtranslator</a>. I edited about 5 strings, and then wanted
to commit my changes. To my surprise, the diff was huge. Apart from obvious changes
in the file header, like changing the team address or X-Generator field, Gtranslator
has reformatted almost every other entry in the file, adding meaningless line breaks
or reflowing the strings I didn't edit.</p>
<pre>
@@ -3092,8 +3093,8 @@ msgstr ""
#: kallithea/templates/admin/permissions/permissions_globals.html:72
msgid ""
-"Write permission to a repository group allows creating repositories "
-"inside that group."
+"Write permission to a repository group allows creating repositories inside "
+"that group."
msgstr ""
#: kallithea/templates/admin/permissions/permissions_globals.html:77
</pre>
<p>Apart from that it has quite a dumb user interface, so I most probably won't ever use it
again unless things improve.</p>
<p>Well, I thought, I need to try <a href="https://userbase.kde.org/Lokalize">Lokalize</a> which I understand
is a Qt4 port of KBabel, which I remember was quite a reasonable translation tool.</p>
<p>Just as with Gtranslator, I created a project, edited one line and hit ‘Save’. As I expected,
Lokalize updated the file header, and also changed the formatting of some entries, though the
number of changes was significantly lower.</p>
<p>Yet the winner of this competition is Weblate, which indeed avoids unnecessary changes as much
as it can, just as advertised. Probably, I'll just stick with it, setting up a local instance.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleKallithea 0.2 released2015-04-10T22:48:00+02:002015-04-10T22:48:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2015-04-10:/2015/04/10/kallithea-0.2-released/<p><small>This post is almost a carbon copy of the Kallithea 0.2 release notes.</small></p>
<p><a href="https://kallithea-scm.org/">Kallithea project</a> have just released Kallithea 0.2. Kallithea is a Python-based GPLv3 source
code management software for web-based hosting of Mercurial and Git repositories.</p>
<p>This release brings many changes since 0.1. Notably, pull requests …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2015/04/10/kallithea-0.2-released/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p><small>This post is almost a carbon copy of the Kallithea 0.2 release notes.</small></p>
<p><a href="https://kallithea-scm.org/">Kallithea project</a> have just released Kallithea 0.2. Kallithea is a Python-based GPLv3 source
code management software for web-based hosting of Mercurial and Git repositories.</p>
<p>This release brings many changes since 0.1. Notably, pull requests system
have been improved, making contributing changes more robust. The visual
appearance has also been refined: modern font-based symbolic icons from
FontAwesome and GitHub Octicons have replaced the previously used bitmap
icons, and revision graphs are now drawn with HiDPI display support.
Kallithea now supports Mercurial 3.3 and Dulwich 0.9.9. Several fixes in
the database code boosted performance significantly.</p>
<p>We have also updated our Javascript libraries: jQuery, CodeMirror and Mergely.
Javascript and CSS code have been cleaned up, with less and less code depending
on Yahoo UI library.</p>
<p>Since 0.1 we have discovered two security issues, so all users are strongly
recommended to upgrade. For more details on these issues, please see our
<a href="https://kallithea-scm.org/security/">Security Notices page</a></p>
<p>For more information, see <a href="https://kallithea-scm.org/">https://kallithea-scm.org/</a> or
<a href="http://docs.kallithea-scm.org/">http://docs.kallithea-scm.org/</a>.</p>
<p>The summary of the changes since 0.1 release is below.</p>
<p>Bug fixes:</p>
<ul>
<li>forms: add CSRF protection to all forms — <a href="https://kallithea-scm.org/security/cve-2015-0276.html">CVE-2015-0276</a></li>
<li>api: don't send internal data unless asked for it — <a href="https://kallithea-scm.org/security/cve-2015-0260.html">CVE-2015-0260</a></li>
<li>middleware: fix <code>force_tls</code> typo in <code>force_https</code> backward compatibility code (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/44">#44</a>)</li>
<li>rebranddb: update user <code>extern_type</code> and <code>_name</code> to ‘<code>internal</code>’ instead of ‘<code>kallithea</code>’ (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/38">#38</a>)</li>
<li>git: do not fail if git is not installed and has been removed from <code>__init__.py</code> backends</li>
<li>git: fix <code>'name' must be bytestring, not unicode</code> error on browsing changesets</li>
<li>git: close SubprocessIOChunker inputstream used for git (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/32">#32</a>)</li>
<li>git: introduce hack for handling git failure on <code>--depth</code> cloning (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/33">#33</a>)</li>
<li>git: fix version detection with unexpected version string (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/71">#71</a>)</li>
<li>git: preserve line endings when calling out to git</li>
<li>hg: fix clone from svn+http urls using hg-svn (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/72">#72</a>)</li>
<li>migrate: add missing import (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/29">#29</a>)</li>
<li>pullrequests: handle pull requests to empty repos (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/27">#27</a>)</li>
<li>pullrequests: when creating PRs, fix handling of new ajax requests while other ajax requests are pending</li>
<li>pullrequests: fix updates for PRs between different repositories</li>
<li>pullrequests: preserve query parameters in pull request overview paging links</li>
<li>compare: workaround unexpected Mercurial behaviour when finding ancestor of null rev</li>
<li>javascript: remove trailing comma to please IE8 (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/39">#39</a>)</li>
<li>download: fix for zip file downloads not being valid zips (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/35">#35</a>)</li>
<li>helpers: fix crash on new users without email (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/28">#28</a>)</li>
<li>middleware: change middleware ordering so we don't buffer hgweb output in redirect</li>
<li>bin: give <code>kallithea_config.py</code> <code>#!/usr/bin/env python</code> so it can be executed directly</li>
<li>bin: reintroduce cleanup-repos paster command</li>
<li>bin: fix <code>update_repoinfo</code> command</li>
<li>urlify: don't include trailing punctuation in markup</li>
<li>urlify: markup of hashes in <code>()</code></li>
<li>styling: don't loop on trying to load kallithea-logo.png after kallithea-logo.svg failed</li>
<li>error: don't crash on <code>/error/document</code> urls</li>
<li>error: don't crash on response without status</li>
<li>admin: prevent deletion of users that are owners of a repository/user group (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/64">#64</a>)</li>
<li>admin: make settings hook name field smaller so it is less likely to overlap with the value field</li>
<li>admin: when scanning for repos to add, ignore removed groups</li>
<li>auth_crowd: fix Admin Group Membership when using the Atlassian Crowd plugin</li>
<li>auth: enable selecting PAM authentication module</li>
<li>auth_ldap: fix user automatically activated with LDAP authentication (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/78">#78</a>)</li>
<li>db: fix beaker cache key for user groups — don't collide with users</li>
<li>db: fix handling of (invalid) unicode email addresses</li>
<li>db: don't use sql 'in' on empty sets in compare — avoid warning of bad performance</li>
<li>db: to the extent it makes sense to have a one byte size limit, make it 255 instead of 256 to please MySQL (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/96">#96</a>)</li>
<li>files: use current revision as default for 'show at' (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/31">#31</a>)</li>
<li>files: fix HTML injection via file names</li>
<li>files: use forward slash as path separator for consistency</li>
<li>files: don't use HTML encoding where not needed (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/74">#74</a>).</li>
<li>feed: urlify and escape the commit description</li>
<li>diff: fix diff of renamed files with whitespace in their names</li>
<li>diff: don't split lines on bare CR as python splitlines do</li>
<li>mergely: update Mergely to v3.3.9 (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/83">#83</a>)</li>
<li>jquery: upgrade to 1.11.1</li>
<li>codemirror: cleanup of integration and update to version 4.7</li>
<li>setup: constrain dulwich to version 0.9.9, fixes <a href="http://www.openwall.com/lists/oss-security/2015/03/22/19">CVE-2015-0838</a></li>
<li>gists: add missing formencode.htmlfill import</li>
<li>ini: Make celeryd.log.level default values uppercase — lowercase might not be recognized and cause failure</li>
<li>notification: handle unicode translations (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/95">#95</a>)</li>
<li>repos: fix redirect after repo creation (and user/group add focus) (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/98">#98</a>)</li>
<li>changeset: don't crash on malformed whitespace parameter — return 400 Bad Request</li>
<li>stats: fix display when no data ready yet</li>
<li>stats: fix "show more" link</li>
</ul>
<p>Features and improvements:</p>
<ul>
<li>ui: use font based icons — FontAwesome and Git Hub Octicons from fontello</li>
<li>ui: HiDPI / Retina support in graphs and other places</li>
<li>paster: add install-iis command to automate IIS handler generation and update documentation</li>
<li>email templates: send text/plain part as well</li>
<li>docs: lots of improvements of structure and content and language</li>
<li>translations: updated using WebLate</li>
<li>admin: show links to added repos after repo scan</li>
<li>admin: show links to created users and groups</li>
<li>admin: when scanning for repos without 'remove', report the repos that could/would be removed</li>
<li>setup: support Mercurial 3.3</li>
<li>db: drop most lazy joins — significant performance improvement</li>
<li>db: add missing indices — significant performance improvement</li>
<li>db: don't commit session if cache invalidation didn't change anything — improves performance</li>
<li>comment: show full username in emails for PR/changeset comments</li>
<li>changelog: added Settings to repo context menu</li>
<li>utils: better display of ages >1 year when in short form</li>
<li>remotes: add support to clone from Mercurial repositories over ssh</li>
<li>hg: reimplement branch head listings more efficiently</li>
<li>pullrequests: use same code and table ui for Repo Pull Requests and My Pull Requests</li>
<li>pullrequests: add delete button to My Pull Requests overview</li>
<li>pullrequests: on 'my pullrequests' show the user's own vote as second column next to 'latest vote'</li>
<li>pullrequests: add option for adding repo owner as reviewer if none assigned</li>
<li>pullrequests: make top pane one big form with meta data and one save button and preview changes in pane below — more like when creating the PR</li>
<li>pullrequests: make 'update' functionality a separate submit button in the big form, automatically enabled when an update changeset is chosen</li>
<li>pullrequests: show graph next to the list of changesets that are available for update</li>
<li>pullrequests: for available changesets, also show changesets that not are descendants and thus not directly available but will be merged in</li>
<li>pullrequests: show unrelated branch heads in the graph too — show the problem instead of trying to explain it</li>
<li>pullrequests: show pending reviewer changes with "(not saved)"</li>
<li>pullrequests: show comment count in top of summary box</li>
<li>diff: improved parsing, be more strict and fail with good error messages</li>
<li>diff: handle GIT delta binary patches</li>
<li>diff: show renamed files as that</li>
<li>diff: make trailing spaces more visible — make vertical line less transparent</li>
<li>diff: show CR (\r) in diffs</li>
<li>comment: warn before leaving page with open comments</li>
<li>comment: clarify shown comment count (inline vs general)</li>
<li>comment: extend next/previous links to global comments (Issue <a href="https://bitbucket.org/conservancy/kallithea/issue/91">#91</a>)</li>
</ul>
<p>Changes (might influence workflows):</p>
<ul>
<li>i18n: en translation has been removed — make sure to update your .ini files to have 'lang =' (nothing)</li>
<li>ini: turn <code>show_revision_number</code> off by default</li>
<li>pullrequests: don't give changeset 'unreviewed' status just because it is added to a PR</li>
<li>pullrequests: tweak readable titles — just append <code>/_/</code> and branch name</li>
<li>pullrequests: only author and admin can close</li>
<li>pullrequests: don't add repo owner as reviewer in all PRs</li>
<li>pullrequests: PRs between different repos should default to same destination/source branch</li>
<li>pullrequests: use <code>--</code> as separator in the automatic text when "updating" pull requests and is it to put latest updates first</li>
<li>diff: don't group diffs based on the kind of change</li>
<li>admin: set current user as owner when running repo scan</li>
<li>changelog: change default view to 100 changesets, max to 2000</li>
<li>date representation: use ISO8601 rather than a specific locale</li>
<li>user groups: drop add/remove all buttons for member selection — they are too dangerous and multi-select can do the same</li>
<li>hg: drop support for hg web.hidden</li>
<li>template: link the last revision in the file browser to the changeset</li>
</ul>
<p>Cleanup:</p>
<ul>
<li>code: Fix typos and language in comments and code</li>
<li>ui: Correct capitalization and improved English text in the UI</li>
<li>javascript: use strict mode</li>
<li>tags: rename old non-Kallithea tags and prefix them with 0.0 to show that Kallithea is superior</li>
<li>javascript: more jQuery, less YUI, less clutter</li>
<li>templates: better structure, less cut'n'paste coding</li>
<li>html: various improvements</li>
<li>css: various improvements</li>
<li>exceptions: avoid silently catching exceptions — especially avoid catch all</li>
<li>tests: stability fixes</li>
<li>tests: remove large unused test fixture</li>
<li>whitespacecleanup.sh: run it regularly to ensure consistent whitespace and avoid spurious changes</li>
<li>controllers: consistently use <code>formfill.render</code> with <code>force_defaults=False</code></li>
<li>gists: use <code>allow_extra_fields</code> and <code>filter_extra_fields</code> in gist forms like in most other forms</li>
<li>json: always use <code>kallithea.lib.compat</code> for json — and nothing else</li>
<li>json: drop simplejson fallback and just use stdlib</li>
<li>db: check for None instead of boolean false if that is what we mean</li>
</ul>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleTired of autotools? Try this: mk-configure2014-03-24T23:30:00+01:002014-03-24T23:30:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2014-03-24:/2014/03/24/mk-configure-tired-of-autotools-try-this/<p><a href="http://sourceforge.net/projects/mk-configure/">mk-configure</a> is a project which tries to be autotools done right.
Instead of supporting an exceedingly large number of platforms, modern and ancient, at costs of generated unreadable
multi-kilobyte shell scripts, mk-configure aims at better support of less platforms, but those which are really in
use today. One of the …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2014/03/24/mk-configure-tired-of-autotools-try-this/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p><a href="http://sourceforge.net/projects/mk-configure/">mk-configure</a> is a project which tries to be autotools done right.
Instead of supporting an exceedingly large number of platforms, modern and ancient, at costs of generated unreadable
multi-kilobyte shell scripts, mk-configure aims at better support of less platforms, but those which are really in
use today. One of the main differences of this project is that it avoids code generation as much as possible.
The author of mk-configure, Aleksey Cheusov, a 38 years old NetBSD hacker from Belarus, uses NetBSD make (<em>bmake</em>)
and shell script snippets instead of monstrous libraries written in <em>m4</em> interleaved with shell scripts. As the result,
there's no need in a separate step of package configuration or bootstrapping the configure script, everything is done
by just running <code>bmake</code>, or a convenience wrapper for it, <code>mkcmake</code>, which prepends a proper library path to bmake
arguments, so you don't have to specify it yourself.</p>
<p>Today, mk-configure is already powerful enough to be able replace autotools for most of the projects, and what is missing
from it can be easily done by hacking the Makefile, which would otherwise be quite simple.</p>
<p>Try it for your project, you may really like it. I already did. And <a href="http://github.com/cheusov/mk-configure/issues">report bugs</a>.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleifupdown and command status handling2014-03-23T18:31:00+01:002014-03-23T18:31:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2014-03-23:/2014/03/23/ifupdown-and-command-status-handling/<p>In 2011, I first tried to fix a <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=547587">Debian bug #547587</a>. The bug was about hook script result codes not being checked, so if a script fails, this isn't detected. Unfortunately, just checking the return code wasn't enough, as lots of scripts didn't care about their return code at all …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2014/03/23/ifupdown-and-command-status-handling/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>In 2011, I first tried to fix a <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=547587">Debian bug #547587</a>. The bug was about hook script result codes not being checked, so if a script fails, this isn't detected. Unfortunately, just checking the return code wasn't enough, as lots of scripts didn't care about their return code at all, so I had to unapply the patch.</p>
<p>Now, after 2.5 years, I think it's time to try again, as most of the scripts have been fixed since then. At the same time, I've changed error handling a little bit further: errors in any commands or scripts during interface configuration are considered fatal, but when interface is deconfigured, errors are ignored. However, this may change break configurations which depend on previous behaviour.</p>
<p>Please report bugs if you find any.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articlehgk misbehaviour with Tk 8.42014-03-16T11:31:00+01:002014-03-16T11:31:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2014-03-16:/2014/03/16/hgk-misbehaviour-with-tk-8-4/<p>Strangely enough, running hgk (a port of gitk to Mercurial, also known as <code>hg view</code>) with Tk 8.4 crashes my X server. Updating both Tk and the X doesn't help. I don't feel like I want to debug X now, but probably that's what I have to do :(</p>
<pre>
Backtrace …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2014/03/16/hgk-misbehaviour-with-tk-8-4/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></pre><p>Strangely enough, running hgk (a port of gitk to Mercurial, also known as <code>hg view</code>) with Tk 8.4 crashes my X server. Updating both Tk and the X doesn't help. I don't feel like I want to debug X now, but probably that's what I have to do :(</p>
<pre>
Backtrace:
0: /usr/bin/X (xorg_backtrace+0x49) [0xb7712ed9]
1: /usr/bin/X (0xb7572000+0x1a4c64) [0xb7716c64]
2: linux-gate.so.1 (__kernel_rt_sigreturn+0x0) [0xb755040c]
3: /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xb711d000+0x772f0) [0xb71942f0]
4: /lib/i386-linux-gnu/i686/cmov/libc.so.6 (__libc_calloc+0xab) [0xb7196d5b]
5: /usr/bin/X (0xb7572000+0x55ca9) [0xb75c7ca9]
6: /usr/bin/X (0xb7572000+0x48005) [0xb75ba005]
7: /usr/bin/X (0xb7572000+0x491c3) [0xb75bb1c3]
8: /usr/bin/X (0xb7572000+0x12c621) [0xb769e621]
9: /usr/bin/X (XkbHandleActions+0x20b) [0xb76c8c1b]
10: /usr/bin/X (XkbProcessKeyboardEvent+0xbc) [0xb76c937c]
11: /usr/bin/X (AccessXFilterPressEvent+0xcd) [0xb76c181d]
12: /usr/bin/X (0xb7572000+0x157675) [0xb76c9675]
13: /usr/bin/X (mieqProcessDeviceEvent+0x1e6) [0xb76f3226]
14: /usr/bin/X (mieqProcessInputEvents+0xfd) [0xb76f335d]
15: /usr/bin/X (ProcessInputEvents+0x14) [0xb75ef3e4]
16: /usr/bin/X (0xb7572000+0x3c25d) [0xb75ae25d]
17: /usr/bin/X (0xb7572000+0x2a51a) [0xb759c51a]
18: /lib/i386-linux-gnu/i686/cmov/libc.so.6 (__libc_start_main+0xf5) [0xb71368c5]
19: /usr/bin/X (0xb7572000+0x2a8f8) [0xb759c8f8]
</pre>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleProcess isolation support in start-stop-daemon2014-03-08T11:17:00+01:002014-03-08T11:17:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2014-03-08:/2014/03/08/process-isolation-support-in-start-stop-daemon/<p>Yesterday I played with LXC a bit, and I liked it, as LXC provides a
very lightweight isolation of processes, much like enchanced chroot.
However, I realised, I don't always need the chroot-like part of LXC,
sometimes what I need is just to make sure the process is unable to …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2014/03/08/process-isolation-support-in-start-stop-daemon/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Yesterday I played with LXC a bit, and I liked it, as LXC provides a
very lightweight isolation of processes, much like enchanced chroot.
However, I realised, I don't always need the chroot-like part of LXC,
sometimes what I need is just to make sure the process is unable to
see the other processes and talk to them in any other way except the
filesystem, but I don't want a whole separate root file system for
that. LXC provides a simple utility, <code>lxc-unshare</code>, which uses
Linux-specific clone(2) call to run a process with new PID, IPC and other
namespaces. However, this utility can't be used for running forking
daemons, as the container is destroyed when its PID 1 exits.</p>
<p>That's why I decided to add the support for process isolation to <code>start-stop-daemon</code>.
I was careful enough to introduce minimal changes to it to make sure they can
be merged back to the version as shipped with <code>dpkg</code>, and at the same time
be buildable separately from the rest of it. Speaking of building, by the way,
this version of <code>start-stop-daemon</code> uses <a href="http://sourceforge.net/projects/mk-configure/">mk-configure</a>,
a light-weight autotools replacement, as its build system.</p>
<p>What I added, from a user's perspective, is a single <code>--isolate</code> option. When
run with this option, <code>start-stop-daemon</code> calls clone(2) just before configuring
the environment of a process it's going to run. The cloned process runs in
a new namespace, and immediately remounts <code>/proc</code>, <code>/dev/shm</code> and <code>/dev/mqueue</code>.
Then it forks, and a forked process executes the daemon. The parent process,
which is PID 1 in the new PID namespace, uses waitpid(2) to monitor its child
processes. As soon as its very first child exits, it talks via a pipe to the process
outside of the container, so that it knows the container has a forked daemon
and it needs to detach. In any case, the container's PID 1 does waitpid(2) in
a loop, checking the process list every time a child terminates. As soon as it's left
alone or a <code>SIGTERM</code> is received, it exits.</p>
<p>The code is published at <a href="https://bitbucket.org/andrew_shadoura/start-stop-daemon-isolate">Bitbucket</a>.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleClearlooks-Phénix update2014-02-05T22:58:00+01:002014-02-05T22:58:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2014-02-05:/2014/02/05/clearlooks-phenix-update/<p>Once upon a time, GTK+ 3.0 was released. That release brought at least one Bad Thing™:
incompatibility with GTK+ 2.x themes. At the same time, previously popular Clearlooks
theme hasn't been ported. Many people didn't like that, but only one decided to DTRT —
to do the Right Thing …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2014/02/05/clearlooks-phenix-update/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Once upon a time, GTK+ 3.0 was released. That release brought at least one Bad Thing™:
incompatibility with GTK+ 2.x themes. At the same time, previously popular Clearlooks
theme hasn't been ported. Many people didn't like that, but only one decided to DTRT —
to do the Right Thing. Jean-Philippe Fleury wrote Clearlooks-Phénix (originally, Clearwaita),
a GTK+ 3 theme which was supposed to have a look and feel as close as possible to the
original Clearlooks. He based his work on an engine of a new GTK+ default, Adwaita theme.
Quite soon, however, GTK+ 3 theme API has changed, and it became easily possible to rewrite
the theme without using any additional theming engines, with just plain GTK+ stuff involved.</p>
<p>Then GTK+ 3.6 came and broke the API once more. Jean-Philippe fixed stuff to work with newer
GTK+ again, and everyone was happy again.</p>
<p>But Empire striked back: GTK+ 3.8 brought more disruptive changes, rendering menus
as ugly as never before. Unfortunately, Jean-Philippe was unable to cope with changes alone,
he set up a mailing list to collectively develop Clearlooks-Phénix, but that didn't help,
and no fix has been released during more than half a year.</p>
<p>As a maintainer and a user of Clearlooks-Phénix, I had to do something with this, as more and
more things needed recent GTK+ 3 to work. After spending some time studying CSS code and playing
with its knobs, I found a solution which proved to be quite simple, and uploaded an updated package.
Unfortunately, the changes aren't in the upstream package yet.</p>
<p>Now, with GTK+ 3.10, stuff is not quite working again. Some changes in GTK+ internals
lead to menu bars not being coloured properly. At the moment of this writing, an updated
package is already available in unstable.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleNot coming to FOSDEM2014-01-27T21:27:00+01:002014-01-27T21:27:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2014-01-27:/2014/01/27/not-coming-to-fosdem/<p>It turnes out moving to a different city takes more time and
effort than I originally expected, so I'm skipping FOSDEM this
year. That's unlike I originally planned to spend the beginning
of February — I had my flight booked already, but apparently that's
not the best idea ever to go …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2014/01/27/not-coming-to-fosdem/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>It turnes out moving to a different city takes more time and
effort than I originally expected, so I'm skipping FOSDEM this
year. That's unlike I originally planned to spend the beginning
of February — I had my flight booked already, but apparently that's
not the best idea ever to go travelling right in the middle of
relocation :)</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleA bit more on TrueCrypt2013-04-13T16:01:00+02:002013-04-13T16:01:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2013-04-13:/2013/04/13/a-bit-more-on-truecrypt/<p>Few days ago I was discussing my last <a href="/2013/01/05/truecrypt-ntfs-3g-loop/">blog post</a> with a colleague of mine, <a href="https://plus.google.com/110593868562394816384/">Lukaš Tvrdý</a>, and he's mentioned that it actually is possible to harmlessly decrypt the TrueCrypted filesystem in online mode, resize it, and encrypt it back again. Well, I decided to try, because I have had …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2013/04/13/a-bit-more-on-truecrypt/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Few days ago I was discussing my last <a href="/2013/01/05/truecrypt-ntfs-3g-loop/">blog post</a> with a colleague of mine, <a href="https://plus.google.com/110593868562394816384/">Lukaš Tvrdý</a>, and he's mentioned that it actually is possible to harmlessly decrypt the TrueCrypted filesystem in online mode, resize it, and encrypt it back again. Well, I decided to try, because I have had some problems with that setup. Apart from init script reordering I had to make (not covered in the post, as I did it later and haven't found time yet to write about that), I ran into a trouble while trying to enable swapping. As the only partition I had was formatted into NTFS, placing a swap file there isn't the best idea ever. I actually tried doing so, but after two deadlocks I had in few hours I had to rethink that. Indeed, as NTFS is implemented in the user space using ntfs-3g, as soon as this process gets swapped out, the system is left helpless. The swap is on the file system driver of which is in the swap, which is on the file system driver of which is... well, you get the idea.</p>
<p>Basically, I got rid of ext3-on-the-loop, and now I have real ext3 in a LUKS container, plus a separate swap partition. Now the other problem is: I still have an encrypted NTFS filesystem which I occasionally need to access, but I don't want to type the pass phrase twice... Something to think about.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleHow to run Debian from a loop device on a TrueCrypt'ed NTFS partition2013-01-05T01:40:00+01:002013-01-05T01:40:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2013-01-05:/2013/01/05/truecrypt-ntfs-3g-loop/<p>After I have changed my job recently I had to meet the security policies which
are enforced in the company I'm now working for. First of all, I'm not allowed
to use my own laptop, and the company-provided laptop has Windows installed.
As my job is, unfortunately, not directly related …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2013/01/05/truecrypt-ntfs-3g-loop/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>After I have changed my job recently I had to meet the security policies which
are enforced in the company I'm now working for. First of all, I'm not allowed
to use my own laptop, and the company-provided laptop has Windows installed.
As my job is, unfortunately, not directly related to Linux, I'm not allowed to
re-install the OS. However, working in the comfortable environment is what I
really need to do my job effectively, so I have designed a workaround.</p>
<p>The workaround is, basically, to install Debian into an ext3 filesystem image,
which itself lies on an NTFS partition, which itself is encrypted using
TrueCrypt. Thus I keep Windows installation unharmed, while I'm still able to
run operating system of my choice, and to keep all the data encrypted, as
policies require. Also, to boot into Debian, I have to boot from the USB stick,
as I'm not sure I can install GRUB at the hard disk without doing any harm to
the fragile TrueCrypt + Windows boot loader duo.</p>
<p>Basically, what I needed to accomplish was the following:</p>
<ul>
<li>Boot Linux, map the encrypted partition using <code>tcplay</code> and <code>device-mapper</code>.</li>
<li>Mount the NTFS filesystem using <code>ntfs-3g</code>.</li>
<li>Mount the ext3 filesystem image using a loop device.</li>
<li>Move the NTFS mountpoint to the new filesystem root.</li>
<li>Switch to the new filesystem root.</li>
</ul>
<p>Everything above is performed from initramfs, thus giving an opportunity to
do that smoothly and to let the USB stick be used to boot the kernel only.</p>
<p>I don't really know how initramfs manipulations are done in distributions other
than Debian, but at least in Debian there's a framework which allows few hook scripts to
be placed under <code>/etc/initramfs-tools</code>, so on the initramfs rebuild some new stuff
may be pulled in.</p>
<p>First of all, we want <code>tcplay</code>, which is a free implementation of TrueCrypt,
to be available in initramfs. For that, we put the following file under
<code>/etc/initramfs-tools/hooks</code>:</p>
<figure class="code">
<figcaption><span>tcplay.sh</span> <a href="https://gist.github.com/4457192">download</a></figcaption>
<div class="highlight"><table class="highlighttable table table-striped"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="ch">#!/bin/sh</span>
<span class="nb">set</span><span class="w"> </span>-e
<span class="nv">PREREQ</span><span class="o">=</span><span class="s2">"dmsetup"</span>
prereqs<span class="w"> </span><span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">PREREQ</span><span class="si">}</span><span class="s2">"</span>
<span class="o">}</span>
<span class="k">case</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">1</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span><span class="k">in</span>
<span class="w"> </span>prereqs<span class="o">)</span>
<span class="w"> </span>prereqs
<span class="w"> </span><span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
<span class="w"> </span><span class="p">;;</span>
<span class="k">esac</span>
.<span class="w"> </span>/usr/share/initramfs-tools/hook-functions
copy_exec<span class="w"> </span>/usr/bin/tcplay<span class="w"> </span>/bin
manual_add_modules<span class="w"> </span>dm_crypt
copy_modules_dir<span class="w"> </span>kernel/crypto
<span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
</code></pre></div></td></tr></table></div>
</figure>
<p>Here, we first require <code>dmsetup</code> to be installed into initramfs, as we depend
on it. Then we copy <code>tcplay</code> itself, and then add module required by it. I've
decided to add all cryptomodules, as I don't know which exactly of them
TrueCrypt may require.</p>
<p>Also, as TrueCrypt is going to request a pass phrase, we need to ensure it gets
access to the console input. I know this is definitely not the best way to
accomplish this, but it was the easiest way I managed to find that worked: to
use <code>openvt</code> utility from <code>console-tools</code> package. The following file goes
to the same directory as the previous one:</p>
<figure class="code">
<figcaption><span>console-tools.sh</span> <a href="https://gist.github.com/4457192">download</a></figcaption>
<div class="highlight"><table class="highlighttable table table-striped"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="ch">#!/bin/sh</span>
<span class="nb">set</span><span class="w"> </span>-e
<span class="nv">PREREQ</span><span class="o">=</span><span class="s2">""</span>
prereqs<span class="w"> </span><span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">PREREQ</span><span class="si">}</span><span class="s2">"</span>
<span class="o">}</span>
<span class="k">case</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">1</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span><span class="k">in</span>
<span class="w"> </span>prereqs<span class="o">)</span>
<span class="w"> </span>prereqs
<span class="w"> </span><span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
<span class="w"> </span><span class="p">;;</span>
<span class="k">esac</span>
.<span class="w"> </span>/usr/share/initramfs-tools/hook-functions
copy_exec<span class="w"> </span>/usr/bin/openvt<span class="w"> </span>/bin
<span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
</code></pre></div></td></tr></table></div>
</figure>
<p>At this point, we have prepared all the required binaries. Now it's time to add
scripts to actually perform the filesystem manipulations.</p>
<p>The first step is to map the encrypted block device. We need to do that before
the root filesystem is mounted, so we put the following script into <code>/etc/initramfs-tools/scripts/init-premount</code>:</p>
<figure class="code">
<figcaption><span>tcplay-local.sh</span> <a href="https://gist.github.com/4457192">download</a></figcaption>
<div class="highlight"><table class="highlighttable table table-striped"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="ch">#!/bin/sh</span>
<span class="nb">set</span><span class="w"> </span>-e
<span class="k">case</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">1</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span><span class="k">in</span>
<span class="w"> </span>prereqs<span class="o">)</span>
<span class="w"> </span><span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
<span class="w"> </span><span class="p">;;</span>
<span class="k">esac</span>
openvt<span class="w"> </span>-c<span class="w"> </span><span class="m">1</span><span class="w"> </span>-f<span class="w"> </span>-w<span class="w"> </span>-s<span class="w"> </span>tcplay<span class="w"> </span>-m<span class="w"> </span>winroot<span class="w"> </span>-d<span class="w"> </span>/dev/disk/by-id/ata-YOUR-DISK-ID-part2<span class="w"> </span>-s<span class="w"> </span>/dev/disk/by-id/ata-YOUR-DISK-ID
<span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
</code></pre></div></td></tr></table></div>
</figure>
<p><code>openvt</code> attaches <code>tcplay</code> to the VT1 and waits for it to get the pass phrase from user.
As the result, the unencrypted block device becomes seen as <code>/dev/mapper/winroot</code>.</p>
<p>Next thing is to mount the NTFS partition:</p>
<figure class="code">
<figcaption><span>ntfs-mount.sh</span> <a href="https://gist.github.com/4457192">download</a></figcaption>
<div class="highlight"><table class="highlighttable table table-striped"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="ch">#!/bin/sh</span>
<span class="nb">set</span><span class="w"> </span>-e
<span class="k">case</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">1</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span><span class="k">in</span>
<span class="w"> </span>prereqs<span class="o">)</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span>tcplay-local.sh
<span class="w"> </span><span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
<span class="w"> </span><span class="p">;;</span>
<span class="k">esac</span>
sleep<span class="w"> </span><span class="m">2</span>
mkdir<span class="w"> </span>-p<span class="w"> </span>/media/winroot
ntfs-3g<span class="w"> </span>/dev/mapper/winroot<span class="w"> </span>/media/winroot
<span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
</code></pre></div></td></tr></table></div>
</figure>
<p>This goes to the same directory. Note that we declare the dependency on <code>tcplay-local.sh</code>.</p>
<p>After we've done that, the root filesystem can be mounted by the usual initramfs script, the
only thing we need to do is to tell it how to mount it and where does it find it. It's done by
adding this to the kernel command line:</p>
<pre>root=/media/winroot/rootfs rootflags=loop rootfstype=ext3</pre>
<p>Of course, your filesystem image should be at <code>/media/winroot/rootfs</code>.</p>
<p>After we have mounted the root filesystem, it may be a good idea to make the underlying NTFS
available for the user; if we don't move the mount point under the new root, it becomes
inaccessible later. This script goes into <code>/etc/initramfs-tools/scripts/init-bottom</code>:</p>
<figure class="code">
<figcaption><span>mount-move.sh</span> <a href="https://gist.github.com/4457192">download</a></figcaption>
<div class="highlight"><table class="highlighttable table table-striped"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="ch">#!/bin/sh</span>
<span class="nb">set</span><span class="w"> </span>-e
<span class="k">case</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">1</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span><span class="k">in</span>
<span class="w"> </span>prereqs<span class="o">)</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span>udev
<span class="w"> </span><span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
<span class="w"> </span><span class="p">;;</span>
<span class="k">esac</span>
<span class="c1"># move the /media/winroot directory to the rootfs</span>
mount<span class="w"> </span>-n<span class="w"> </span>-o<span class="w"> </span>move<span class="w"> </span>/media/winroot<span class="w"> </span><span class="si">${</span><span class="nv">rootmnt</span><span class="si">}</span>/media/winroot
<span class="c1"># create a temporary symlink</span>
nuke<span class="w"> </span>/media/winroot
ln<span class="w"> </span>-s<span class="w"> </span><span class="si">${</span><span class="nv">rootmnt</span><span class="si">}</span>/media/winroot<span class="w"> </span>/media/winroot
<span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
</code></pre></div></td></tr></table></div>
</figure>
<p>It doesn't check for existance of <code>/media/winroot</code> mountpoint in the new root directory, so
you should create it beforehand, as at this point the root filesystem is mounted read-only.</p>
<p>Basically, this is enough to make system boot. However, there's a problem at shutdown:
<code>sendsigs</code> initscript first terminates and then kills the <code>ntfs-3g</code> driver, so
the root filesystem stays unsynchronised and isn't cleanly unmounted. Originally, to solve
this I came up with my own custom init script, but apparently there's an easier way. <code>sendsigs</code>
consults <code>/run/sendsigs.omit.d</code> directory for PID files of processes it shouldn't kill.
On the other hand, <code>ntfs-3g</code> provides an initramfs script which puts a PID of <code>ntfs-3g</code>
process into this directory <strong>if</strong> the root filesystem is on NTFS, or if <code>LOOPFSTYPE</code> variable
says <code>ntfs</code> or <code>ntfs-3g</code>. So it should be enough to place a file into <code>/etc/initramfs-tools/conf</code>:</p>
<pre>LOOPFSTYPE=ntfs-3g</pre>
<p>Finally, to regenerate the initramfs, run <code>update-initramfs -k all -u</code> and copy it to your bootable medium.</p>
<p>Well, test, enjoy using this (if you need to), report bugs!</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleBohdan Zograf and so-called “Belorussian” translations2013-01-01T02:01:00+01:002013-01-01T02:01:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2013-01-01:/2013/01/01/bohdan-zograf-and-so-called-belorussian-translations/<p>I'd like to bring some attention to activity of a person mostly known as Bohdan Zograf. If you Google that name, you'll find that he seems to be a person who knows Belarusian language very well, and is interested in translating as many texts as he can into Belarusian for …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2013/01/01/bohdan-zograf-and-so-called-belorussian-translations/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>I'd like to bring some attention to activity of a person mostly known as Bohdan Zograf. If you Google that name, you'll find that he seems to be a person who knows Belarusian language very well, and is interested in translating as many texts as he can into Belarusian for no money. Unfortunately, he isn't. Trust me, I'm really a native speaker, I was born in Minsk, Belarus, and have lived there for 25 years of my life (at least this person: (<a href="http://pgp.mit.edu:11371/pks/lookup?op=vindex&search=0xC61A895E85EE3E0E">1</a>, <a href="http://pgp.mit.edu:11371/pks/lookup?op=vindex&search=0x798F1E35CB4D38A9">2</a>) may prove I really am the person I'm telling you I am, if you're interested). Said that, I think I really have a right to say: those translations are fake. These texts are just machine-translated versions of the original articles or web pages, published in some strange weblog at some strange web site without being structured or systematised. This already <a href="http://advogato.org/person/redi/diary/242.html">has been</a> pointed out by <a href="http://advogato.org/person/redi/">Jonathan Wakely</a>, but, well, some people may not believe him as he doesn't seem to know Belarusian.</p>
<p>Anyway, one more interesting detail: why would a person with a non-Belarusian name and <a href="http://lists.w3.org/Archives/Public/www-validator/2011Apr/0008.html">a Hungarian telephone number</a> who can't really properly spell the name of the country (Belarus, not Belorussia) and the language (Belarusian, not Belorussian — well, lots of people do that mistake, I must admit), say that Belarusian is his mother tongue do a translation asking to link him back for that? Doesn't that seem strange a bit? It does for me.</p>
<p>I don't really understand the reasons behind that, and I can't really see what is
he going to achieve by doing this, but, as Jonathan said, I believe that <em>all
spammers must die.</em> Well, not necessarily literally, but at least they must stop
spamming, shouldn't they?</p>
<p><strong>Bohdan Zograf is a spammer.</strong> Don't do what he asks you to do, as doing so you
help spammers.</p>
<p>P.S. Spread the word.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleLinux, snd_hda_intel and Sigmatel STAC92002012-09-05T23:35:00+02:002012-09-05T23:35:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2012-09-05:/2012/09/05/linux-snd-hda-intel-and-sigmatel-stac9200/<p>Strange and interesting thing has happened to me recently. I'm a user of Dell
D620 laptop, which has Intel's HDA controller and Sigmatel's STAC9200 codec.
This has always worked perfectly fine, and in my mixer I could see at least two
volume controls: Master and PCM. Changing volume using both …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2012/09/05/linux-snd-hda-intel-and-sigmatel-stac9200/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Strange and interesting thing has happened to me recently. I'm a user of Dell
D620 laptop, which has Intel's HDA controller and Sigmatel's STAC9200 codec.
This has always worked perfectly fine, and in my mixer I could see at least two
volume controls: Master and PCM. Changing volume using both worked.</p>
<p>Once I've upgraded my Linux 3.2 to 3.4, and have noticed that Master volume
control is no more. What's up I thought, but did nothing. Update to 3.5 hasn't
fixed the problem. Okay, it's time to <code>bisect</code> stuff.</p>
<p>Bisection has shown that this commit has introduced the change which affected
me:</p>
<pre>
From 2faa3bf15ba69fa12bc53926b88982b3875abb3f Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 12 Mar 2012 12:30:22 +0100
Subject: [PATCH] ALSA: hda - Rewrite the mute-LED hook with vmaster hook in patch_sigmatel.c
<…>
Also, this patch changes the code to create vmaster always even on
STAC9200 and STAC925x. The former "Master" on these chips are renamed
as "PCM" now.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
</tiwai@suse.de></tiwai@suse.de></pre>
<p>That looks very strange, as it means there wasn't PCM volume control. And indeed,
compiling and loading kernel module from Linux 3.1 brings Master volume control
back, but PCM volume control disappears.</p>
<p>More over, when I looked up into the datasheet, I've found no mention of PCM
volume control there:</p>
<p><img alt="" src="/images/posts/stac9200-1.png"/></p>
<p><img alt="" src="/images/posts/stac9200-2.png"/></p>
<p>I don't understand how could that happen and how to solve this. I've mailed
Takashi on this regard, so probably he may tell me something.</p>
<p><em>Update</em>: With a bit of my help, Takashi has solved the problem: https://lkml.org/lkml/2012/9/28/682</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleRemoving accounts from Android devices2012-05-07T03:32:00+02:002012-05-07T03:32:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2012-05-07:/2012/05/07/removing-accounts-from-android-devices/<p>It's a well-known problem that Android offers no easy way to completely remove
the primary Google account, at least sometimes.</p>
<p>Well, there's one not really easy for people not involved with computer stuff,
but at least it works.</p>
<p>Once you have <code>adb shell</code> working, you need to log into your …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2012/05/07/removing-accounts-from-android-devices/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>It's a well-known problem that Android offers no easy way to completely remove
the primary Google account, at least sometimes.</p>
<p>Well, there's one not really easy for people not involved with computer stuff,
but at least it works.</p>
<p>Once you have <code>adb shell</code> working, you need to log into your Android device and type <code>sqlite3 /data/system/accounts.db</code>.
That's the place where accounts are actually stored. In that database, there are tables named <code>accounts</code>, <code>grants</code>
and <code>authtokens</code>. Those you need to clean up:</p>
<pre>
SQLite version 3.5.9
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select _id,name from accounts;
1|user@gmail.com
sqlite> delete from authtokens where accounts_id=1;
sqlite> delete from grants where accounts_id=1;
sqlite> delete from accounts where _id=1;
sqlite> select _id,name from accounts;
</pre>
<p>After that it may be a good idea to restart the device, but I'm not sure it's really needed.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleifupdown news2012-04-19T22:28:00+02:002012-04-19T22:28:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2012-04-19:/2012/04/19/ifupdown-news/<p>A new version of ifupdown has been uploaded to experimental yesterday, which
brings some important changes.</p>
<p>First of all, now it's possible to specify default values for various
interface configuration options. This eliminates the need of hard coding
of them in C source, as Ubuntu has been doing for some …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2012/04/19/ifupdown-news/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>A new version of ifupdown has been uploaded to experimental yesterday, which
brings some important changes.</p>
<p>First of all, now it's possible to specify default values for various
interface configuration options. This eliminates the need of hard coding
of them in C source, as Ubuntu has been doing for some time. End users
are not affected by this change at all, of course.</p>
<p>Second, now ifup behaves differently when it's called with <code>--all</code> option.
Previously, that was causing all interfaces marked as 'auto' to be brought
up. Now, it does exactly the same if <code>--allow</code> option isn't used. Otherwise,
it brings up the interfaces which are declared to belong to a specified
class using allow-* directive. In other words, 'auto' directive indeed
declares interface as belonging to a class 'auto', and the default class for
ifupdown is also 'auto', so when user runs <code>ifup -a</code> only those interfaces
are brought up.</p>
<p>Also, when called with <code>--all</code>, both ifup and ifdown now also call hook
scripts before doing anything and just after that. Specifically, before
bringing interfaces up, it calls pre-up scripts with a special interface
name and a special address family (which can't happen otherwise), and calls
post-up scripts after doing everything it needs. Same happens with ifdown,
but it calls different scripts, of course. This feature helps to avoid
manual parsing of <code>/etc/network/interfaces</code> and <code>/run/network/ifstate</code> as
mountnfs script did (and still does), for example. In theory, exactly none
of the existing scripts should be broken by this change. At least, I couldn't
find any of distribution-supplied scripts which could break. Also, Network
Manager already uses similar approach, so if anything can break, it's been
broken for a long time already.</p>
<p>One more change is related to the initscript. <code>/etc/init.d/ifupdown</code> is no
more. However, ifupdown now provides <code>/etc/init.d/networking</code> instead of
netbase. This means, the next version of netbase needs to drop it, and
also setting up Breaks relationship would be cool. The script itself has
been changed a bit. Apart from other things, now it supports <code>reload</code> command
properly, grabbing the current interfaces state and bringing those interfaces
back up. Also, <code>start</code> command now tries to bring up interfaces which are
specified with 'allow-hotplug' if they can be brought up.</p>
<p>Cool news for Ubuntu maintainers and everyone else interested: now ifupdown
supports ifquery interface previously available in Ubuntu only. It has some
bugs fixed, and now seems to work properly with mappings and already-up
interfaces.</p>
<p>Finally, <code>/run</code> transition has almost finished, so please if you opened any
related bugs, please test and report if they still need fixing.</p>
<p>Also, this version (with one more bug discovered while preparing this post
fixed) is going to be upload to unstable as soon as enough people test it
to be sure it's not going to Break Everything At All. In that upload, I
plan to temporarily unapply a controversial patch already discussed on
debian-devel@ which changed the processing of hook scripts' return values.</p>
<p>Please do test and report any bugs you find.</p>
<p>And, of course, a short summary of the changes:</p>
<ul>
<li>Prefer isc-dhcp-client to dhcp3-client (also closes: #422885).</li>
<li>Let dhclient fail when no lease can be acquired (Closes: #420784).</li>
<li>Raise command-line options priority over <code>/etc/network/interfaces</code>
(Closes: #657743).</li>
<li>Prevent aliases and VLANs from putting the main interface down
(Closes: #656270).</li>
<li>Make iproute2 calculate the broadcast address (LP: #924880).</li>
<li>Shut udhcpc down correctly (Closes: #338348).</li>
<li>Update the rules according to <code>/run</code> migration.</li>
<li>Pass hardening flags from dpkg-buildflags (Closes: #661243).</li>
<li>Implement ifquery interface (Closes: #568479).<ul>
<li>Make ifquery process mappings (LP: #850166).</li>
<li>Ensure ifquery always has no_act turned on.</li>
</ul>
</li>
<li>Change <code>--all</code> behaviour:<ul>
<li>If ifup or ifquery is called with the <code>--all</code> option, if doesn't just
bring up all interfaces marked as "auto", but all interfaces of a
specified class, "auto" by default. For the most uses, this doesn't
change anything, but lets all the interfaces of a specific class to be
brought up or queried.</li>
</ul>
</li>
<li>Support cross-compilation, move Debian-specific things out of
the Makefile (Closes: #666084).</li>
<li>Take networking init script over from netbase package.<ul>
<li>Add reload action which reconfigures all interfaces currently
configured.</li>
<li>Add LSB Description field.</li>
<li>Remove <code>/usr</code> from PATH.</li>
<li>Merge ifupdown initscript in.</li>
<li>Improve warning messages.</li>
<li>Don't use redirection hacks when parsing <code>/proc/mounts</code> and <code>/proc/swap</code>.</li>
<li>Document all supported subcommands.</li>
<li>On start, try to configure hotplug interfaces if they seem to be ready.
Ignore errors if they fail to configure for some reason (for example,
if the interface happens to be renamed by udev before it's fully
configured).</li>
<li>Override Lintian's false positives.</li>
</ul>
</li>
<li>Remove <code>/etc/default/ifupdown</code>.</li>
<li>Call hook scripts when processing all interfaces:<ul>
<li>If ifupdown is called with the <code>--all</code> option, before or after doing
anything to the interfaces, it calls all the hook scripts (pre-up or
down) with IFACE set to "--all", LOGICAL set to the current class
specified by the <code>--allow</code> option (or "auto" if it's not set),
ADDRFAM="meta" and METHOD="none".</li>
</ul>
</li>
<li>Fix IPv6 issue on kFreeBSD.</li>
<li>Update test suite.</li>
<li>Improve manual pages.</li>
<li>Bump Standards-Version to 3.9.3.</li>
<li>Also closes: #535226:<ul>
<li>In 0.7~alpha5, "auto" method has been added.</li>
</ul>
</li>
</ul>
<p>Also posted to debian-devel@ maillist.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleGTK+ 3 done right2012-03-28T13:02:00+02:002012-03-28T13:02:00+02:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2012-03-28:/2012/03/28/gtk-plus-3-done-right/<p>Ever wanted your GTK+ 3 look better? Unsatisfied with the default settings of Adwaita theme?
Add these configuration files to your <code>~/.config/gtk-3.0</code>:</p>
<figure class="code">
<figcaption><span>gtk.css</span> <a href="https://gist.github.com/2225446">download</a></figcaption>
<div class="highlight"><pre><span></span><code><span class="na">.menu</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">border-style:</span><span class="w"> </span><span class="nf">solid</span><span class="c1">;</span>
<span class="w"> </span><span class="nl">border-width:</span><span class="w"> </span><span class="err">1</span><span class="c1">;</span>
<span class="err">}</span>
<span class="na">.menubar</span><span class="w"> </span><span class="no">.menuitem</span><span class="w"> </span><span class="p">*:</span><span class="no">prelight</span><span class="p">,</span>
<span class="na">.menubar</span><span class="w"> </span><span class="no">.menuitem</span><span class="p">:</span><span class="no">prelight</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">background-color:</span><span class="w"> </span><span class="err">@</span><span class="nf">theme_selected_bg_color</span><span class="c1">;</span>
<span class="w"> </span><span class="nl">color:</span><span class="w"> </span><span class="err">@</span><span class="nf">theme_selected_fg_color</span><span class="c1">;</span>
<span class="err">}</span>
</code></pre></div>
</figure>
<p>This will add some nice borders to menus …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2012/03/28/gtk-plus-3-done-right/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Ever wanted your GTK+ 3 look better? Unsatisfied with the default settings of Adwaita theme?
Add these configuration files to your <code>~/.config/gtk-3.0</code>:</p>
<figure class="code">
<figcaption><span>gtk.css</span> <a href="https://gist.github.com/2225446">download</a></figcaption>
<div class="highlight"><pre><span></span><code><span class="na">.menu</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">border-style:</span><span class="w"> </span><span class="nf">solid</span><span class="c1">;</span>
<span class="w"> </span><span class="nl">border-width:</span><span class="w"> </span><span class="err">1</span><span class="c1">;</span>
<span class="err">}</span>
<span class="na">.menubar</span><span class="w"> </span><span class="no">.menuitem</span><span class="w"> </span><span class="p">*:</span><span class="no">prelight</span><span class="p">,</span>
<span class="na">.menubar</span><span class="w"> </span><span class="no">.menuitem</span><span class="p">:</span><span class="no">prelight</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">background-color:</span><span class="w"> </span><span class="err">@</span><span class="nf">theme_selected_bg_color</span><span class="c1">;</span>
<span class="w"> </span><span class="nl">color:</span><span class="w"> </span><span class="err">@</span><span class="nf">theme_selected_fg_color</span><span class="c1">;</span>
<span class="err">}</span>
</code></pre></div>
</figure>
<p>This will add some nice borders to menus as well proper background to menu items.</p>
<figure class="code">
<figcaption><span>settings.ini</span> <a href="https://gist.github.com/2225446">download</a></figcaption>
<div class="highlight"><pre><span></span><code><span class="k">[Settings]</span>
<span class="na">gtk-theme-name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">Adwaita</span>
<span class="na">gtk-fallback-icon-theme</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">gnome</span>
<span class="na">gtk-font-name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">Sans 9</span>
</code></pre></div>
</figure>
<p>And this will set font to <code>Sans 9</code> and not anything else which is for some reason is the default.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articlePiano man2011-12-22T16:21:00+01:002011-12-22T16:21:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2011-12-22:/2011/12/22/piano-man/<p>Those who had chance to be in the 'Stolitsa' shopping mall in the centre of
Minsk yesterday, could enjoy a wonderful performance which was happening there.</p>
<p>There's a grand piano installed in the central hall of this mall. I guess
that piano was supposed to advertise some company which sells …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2011/12/22/piano-man/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Those who had chance to be in the 'Stolitsa' shopping mall in the centre of
Minsk yesterday, could enjoy a wonderful performance which was happening there.</p>
<p>There's a grand piano installed in the central hall of this mall. I guess
that piano was supposed to advertise some company which sells them, but that
day there was something completely different. That piano wasn't silent yesterday.
A young man was playing classics on it.</p>
<p><img alt="" src="https://lh3.googleusercontent.com/-sjQUt5YEGEI/TvMsHt7lptI/AAAAAAAAFs4/3Xh4TuleN7I/s640/DSCF3239.JPG"/></p>
<p>This impromptu concert gathered many people who were just passing by, but the
sounds of beautiful music enchanted them and made them stay for a while.</p>
<p><img alt="" src="https://lh5.googleusercontent.com/-fbm07SbLz5Q/TvMtHa1knyI/AAAAAAAAFts/SGFKdx9m8I0/s640/S0873395.JPG"/></p>
<p>Young musician had a great success; people were applausing after every melody he played.</p>
<p><img alt="" src="https://lh6.googleusercontent.com/-INNzgRNfl5M/TvMsnev5p8I/AAAAAAAAFuI/_L6oA_7jnqE/s720/S0583262.JPG"/></p>
<p>After the performance, I asked the musician few questions. I'm no journalist, but at least I tried my best :)</p>
<p _="%" endblockquote="">{% blockquote %}
'What's your name?'
'Dmitry'.
'Dmitry, why are you here today? Is there any special reason for this concert?'
'Not really. I have some free time, so I went to the administration of the shopping mall and asked them if I can come here to play. They said, sure, of course, any time you want if you have enough free time. So I'm here :)'
'So, it's just like you saw this 'unused' grand piano and decided to use it?'
'Yes!' (laughs)
'So, this isn't some kind of special promotion or anything like that?'
'Not at all; of course, they're interested in this, but...'
'But in general, this is based entirely on your enthusiasm, yes?'
'Yes, exactly'.
'One more question, about repertoire. What do you play?'
'Next time I'll bring a play list :) Well, I don't quite remember in what order I played music. Of course, I play well-known, popular things'.
'Anyway, it was really great! Good luck to you!'
'Thanks!'</p>
<p><img alt="" src="https://lh6.googleusercontent.com/-fM5Rf97Ehcc/TvMtxY3R3uI/AAAAAAAAFuE/xlNzkfqBxT4/s640/S0883398.JPG"/></p>
<p>The rest of the photos can be found here:</p>
<p><embed flashvars="host=picasaweb.google.com&hl=en_GB&feat=flashalbum&RGB=0xefefef&feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2FAndrew.Shadoura%2Falbumid%2F5688939150688056913%3Falt%3Drss%26kind%3Dphoto%26hl%3Den_GB" height="400" pluginspage="http://www.macromedia.com/go/getflashplayer" src="https://picasaweb.google.com/s/c/bin/slideshow.swf" type="application/x-shockwave-flash" width="600"/></p>
<p>And some videos here:</p>
<iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/Fravrpu79SU" width="420"></iframe>
<p>Who knows, maybe he will be a famous pianist one day. At least I hope he will, so let's wish him the best luck.</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleSixxs suxxs?2011-12-13T16:48:00+01:002011-12-13T16:48:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2011-12-13:/2011/12/13/sixxs-suxxs/<p>Recenly I've decided to register at Sixxs to be able to use IPv6 at my new
location as they seem to use tunnelling protocol which bypasses NAT, so that
was exactly what I needed. I'm a long time HE.NET user, so I expected the same
quality of service and …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2011/12/13/sixxs-suxxs/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>Recenly I've decided to register at Sixxs to be able to use IPv6 at my new
location as they seem to use tunnelling protocol which bypasses NAT, so that
was exactly what I needed. I'm a long time HE.NET user, so I expected the same
quality of service and ease of use. I went to their website and filled in the
registration form.</p>
<p>Soon I got the reply: 'User Rejected'</p>
<pre>
The reason specified was:
Either give full valid information or don't signup, see http://www.sixxs.net/faq/account/?faq=address
</pre>
<p>I replied, 'I'm sorry, in which part the information wasn't complete or valid?'</p>
<p>Their reply was:</p>
<pre>
We where unable to verify the address in combination with your name.
Please provide full proper and valid details.
</pre>
<p>Well, as I've already done that, I've sent them it again, carefully putting
diacritics where needed:</p>
<pre>
> We where unable to verify the address in combination with your name.
How do you verify that?
> Please provide full proper and valid details.
My current address is: ..... ####/##, ### ## ......, ......... The
mobile phone is +4.. ... ... .... And that's exactly the information I
provided you with, it's full, proper, correct and valid.
It appears to be completely lacking any respect to treat everyone this
way as if I were a malicious person or something :(
</pre>
<p>They replied:</p>
<pre>
> How do you verify that?
By asking your local government if the information is valid.
>> Please provide full proper and valid details.
>
> My current address is: ..... ####/##, ### ## ......, .......... The
> mobile phone is +4.. ... ... .... And that's exactly the information I
> provided you with, it's full, proper, correct and valid.
That is not the information you provided.
> It appears to be completely lacking any respect to treat everyone this
> way as if I were a malicious person or something :(
I would state it the other way around in that when one does not provide
full valid details one is doing that to us.
</pre>
<p>Conversation continues:</p>
<pre>
>> That is not the information you provided.
>
> That's exactly what I typed into the box on-site with exception for
> diacritics.
Nonsense, you provided:
..... ####/##
.......
........
That does not contain the zip code you supplied above.
> Also, I'm not sure local government is able to provide you
> with detailed information as I rent this flat from a different person
> whose name is M.... S..... (but you haven't asked me of that, have you?)
Clearly you are not providing full valid details.
Nevertheless, our check was correct.
>>> It appears to be completely lacking any respect to treat everyone
>>> this way as if I were a malicious person or something :(
>
>> I would state it the other way around in that when one does not
>> provide full valid details one is doing that to us.
>
> I did provide full valid details, and I guess I deserve something more
> than just sending automated reply that I'm 'rejected' if that
> information isn't enough.
You don't deserve anything as you are wasting our time and resources.
Greets,
Jeroen
</pre>
<p>Is it always like that or am I missing something?</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleBinary watch: NG2011-11-30T16:39:00+01:002011-11-30T16:39:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2011-11-30:/2011/11/30/binary-watch-ng/<p>LED binary watch is a one of the most common geek gadgets available. The only problem with binary watch is that while it's done to be 'cool' and unusual, it's also not very convenient to use even for geeks, at least in my opinion. I think so because it fundamentally …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2011/11/30/binary-watch-ng/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>LED binary watch is a one of the most common geek gadgets available. The only problem with binary watch is that while it's done to be 'cool' and unusual, it's also not very convenient to use even for geeks, at least in my opinion. I think so because it fundamentally breaks the way people use watch usually. Correct me if I am wrong, but in my opinion the exact numbers don't have any real meaning for everyone who uses watch. What's important is which part of some interval of time is now: morning, evening, noon or midnight, and a fraction which tells us how far we are from one important point in time or from another. The same applies to shorter time intervals: usually an hour's divided into quarters or 5-minute intervals.</p>
<p>So, I'd like to propose a different approach.</p>
<p>First, we divide twenty-four hours into intervals of 3 hours each, and encode this in binary. Thus, any time between 12:00 and 14:59 will be represented by a code <code>0100</code>. To specify the exact hour inside that interval, we append its number in binary to the code above, so for 13:00 we get <code>0100.01</code>. The code <code>.11</code> isn't used in this approach at all.</p>
<p>Next, the same we can do to minutes. Two digits can be used to specify an hour quarter. To specify the exact minute, we add four more digits; the code <code>.1111</code> isn't used again.</p>
<p>Now, some examples:</p>
<p><code>12:34 → 12+00 : 30+04 → 0100.00 : 10.0100</code></p>
<p><code>03:27 → 03+00 : 15+12 → 0001.00 : 01.1100</code></p>
<p>Anyone to produce such a binary watch? ;)</p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/articleExtra large image editing2009-03-24T11:04:00+01:002009-03-24T11:04:00+01:00Andrej Shadurahttps://shadura.me/tag:blog.shadura.me,2009-03-24:/2009/03/24/extra-large-image-editing/<p>How often do you need to do something with extra-large images? Usually, I don't need to, but recently I've received one such an image, and really needed to crop it. That image was 21 MiB 16 Kpixel×12 KPixel aerial image in a JPEG file. As anybody knows, JPEG files …<footer><a rel="full-article" class="read-more btn btn-primary" href="/2009/03/24/extra-large-image-editing/">Read more <span class="glyphicon glyphicon-chevron-right"></span></a></footer></p><p>How often do you need to do something with extra-large images? Usually, I don't need to, but recently I've received one such an image, and really needed to crop it. That image was 21 MiB 16 Kpixel×12 KPixel aerial image in a JPEG file. As anybody knows, JPEG files can be converted without decoding the whole image in the memory, you can read <a href="http://en.wikipedia.org/wiki/JPEG">why</a> on the Wikipedia. You just need to go through all image blocks sequentially and write them in the new format. If the image is progressive JPEG, this is even easier. The same with cropping: you can just skip some image blocks without decoding them.</p>
<p>I was surprised when discovered that my usual helper programs couldn't crop this file without eating all my memory and disk space (my laptop has limited both). ImageMagick's convert and couldn't do the task: convert got 795 MiB virt and 300 MiB res, and created 1.2 GiB temp file, so I killed it. nip2, while it was recommended by some people, wasn't able to work for some reason, it just couldn't load the image at all.</p>
<p>I was ready to write my own JPEG re-encoder when I've found <a href="http://packages.debian.org/libjpeg-progs">jpegtran</a>. It was written by <a href="http://ijg.org/">IJG</a> (Independent JPEG Group). This program was able to do anything I needed. It can crop, flip, flop, rotate, transpose and transverse images, convert them to greyscale, re-optimize, and make JPEG progressive. Also you can control memory usage, so it will not make you system unresponsive by eating it all.</p>
<p>Cropping image is as easy as this:</p>
<p><code>$ jpegtran -crop 640x480+0+0 in.jpg > out.jpg</code></p>http://activitystrea.ms/schema/1.0/posthttp://activitystrea.ms/schema/1.0/article