Search Results: "spa"

17 February 2014

Chris Lamb: The effect of pedestaling on TT bike position

To "pedestal" an aerobar means to elevate the bars above the basebar using risers instead of using headset spacers:
https://chris-lamb.co.uk/wp-content/2014/pedestal1.jpg

David Millar, 2010 Giro d'Italia.

You might do this for a few reasons: https://chris-lamb.co.uk/wp-content/2014/teardrop_vs_cylinder.jpg So, assuming you currently have a bike that uses headset spacers, what would be the effect on your position if you were to replace, say, a 10mm headset spacer with a 10mm armrest riser? First, let us consider the effect of removing the headset spacer. The crucial insight is that removing a 10mm spacer will not lower the stack height ie. the vertical distance relative to the bottom bracket by 10mm. This is because spacers are not oriented perpendicular to the ground; they are stacked along the steerer tube at the head tube angle of the frame. We will assume a head tube angle of 72.5 degrees. We can calculate that removing a 10mm spacer will reduce the stack height by:
sin(72.5 )   10mm = 9.54mm
... and by the same argument it will also increase the effective reach ie. the horizontal distance relative to the bottom bracket by:
cos(72.5 )   10mm = 3.01mm
Next, let us consider the impact of adding the riser. These are oriented perpendicular to the ground, so its addition makes no further change to the reach. However, we can now calculate the overall change in stack height:
  stack = -(sin(72.5 )   10mm) + 10mm = 0.46mm
We can then repeat the calculation for any length of replacement:
Replacement (mm) stack (mm) reach (mm)
10 +0.46 +3.01
20 +0.93 +6.01
30 +1.39 +9.02
40 +1.85 +12.0
50 +2.31 +15.0
60 +2.78 +18.0
From this table, I can discover that if I were to replace 30mm of headset spacers with 30mm of risers it would:
  1. Increase my effective stack height by 1.39mm (likely neglible).
  2. Increase my reach by 9.02mm. This might require me to use a shorter stem to get the same position. If that was undesirable for example, if was already using an extremely short stem I might be forced to abandon the idea altogether.
Three further considerations must be noted:
  1. The resultant low height of the base bar could be quite drastic and prevent you breathing properly whilst climbing.
  2. Having the steerer tube cut down after to removing headset spacers will reduce the resale value of your bike.
  3. You might need to re-cable your brakes as you may have changed the distance the cables must span.
(It may seem odd to provide results for up to 60mm of headset spacers when such a large number of spacers would at the very least void one's warranty. However, I suspect such setups are transiently common within the confines of a fitting studio.)

Martin Zobel-Helas: Have YOU registered Services at Debian Services Census?

Enrico and me have just started a census on Debian Services floating around, and we want YOU to participate!

The Debian Services Census is an attempt to gather detailed information about software services for the Debian community. It doesn't matter where these services live or who provides them. For now we are only interested in their existence.

Services can be anything from the mail forwarding service for @debian.org addresses that lives on master.debian.org operated by DSA, web applications, email bots, command line scripts you can run on debian.org machines, automated package checkers that report bugs to people, Debian-related services that people run on their own infrastructure like screenshots.debian.net and son on. Have a look at https://wiki.debian.org/Services for more examples.

If you think it's a service, then we think it's a service too and we want to know about it. Feel free to contribute data whether you are the maintainer of that service or not.

Here is how to let us know about the service:
  • please visit https://wiki.debian.org/Services and verify if the service is already listed there
  • if the service you had in mind is *not* listed, please create an entry for it using the "Add a new service" button.
If you are the maintainer of a service, we also encourage you to subscribe to the debian-services-admin@lists.debian.org mailing list, which is a low-traffic list and should be the contact point for inter-service communication and coordination.

Update: Up to now, 51 services have been registered (most of them within 24 hours after the d-d-a mail, WOW), but we are sure that there are a lot of more services, that still need to be registered. Help us to get a complete list!

Paul Wise: Join the Process Identifier Preservation Society today!

Process Identifiers (PIDs) are a scarce resource. On Linux they are only 15 bits by default. The Process Identifier Preservation Society (PIPS) aims to reduce abuse and wastage of the PID space. To join the society please read the following advice.

Common issues Several languages generally allow you to run all your code in one process. Some of the code that you might want to incorporate or use is not available in the form of ELF libraries or language specific libraries but only in the form of ELF binaries or interpreted scripts. As a result using additional PID space is sometimes unavoidable. Many languages have multiple methods of starting external processes and usually some of them waste PID space by running commands in a shell. You can avoid those methods or use the exec builtin to preserve the shell PID. It might be tempting to explicitly use shell in languages that don't allow implicit shell use but that just wastes extra PIDs. Several languages allow you to fork one process into two, this uses an extra PID and is to be avoided unless necessary.

Shell Programs written in the shell languages use a lot of PIDs. Even shells that have a lot of shell builtins (like busybox sh) appear to use the PID space by forking a child process. To join PIPS you should just stop writing programs in shell or use as many builtins as possible and use exec to preserve PIDs.

Init Several init systems are written in or use shell extensively and thus eat huge bowls of PIDs for breakfast. To join the PIPS you should switch away from sysvinit, openrc, init=/bin/sh etc.

C/C++ The common issues section applies to the C/C++ language. To join PIPS you should rewrite your code to use fork()+exec(), g_spawn*() or libpipeline instead of the g_spawn_command_line*(), system() and popen() functions.

Perl The common issues section applies to the Perl language. To join PIPS you should rewrite your code to avoid backticks and only pass arrays to the system(), open(), open2(), open3() functions.

PHP The common issues section applies to the PHP language. To join PIPS you should rewrite your code to use pcntl_exec() instead of backticks, exec(), system(), passthru(), shell_exec(), popen() and proc_open(). Apparently pcntl_exec() is disabled by default on Debian and pcntl_* are often unavailable so you should just not spawn processes. You could also just drop PHP already.

Python The common issues section applies to the Python language. To join PIPS you should rewrite your code to use the subprocess module and avoid passing shell=True to the subprocess.Popen() function. The os.system(), os.popen() functions and the commands module all run their commands in a shell, wasting PID space. The popen2 module requires passing arrays instead of strings in order to avoid the command being run in a shell.

Java The common issues section applies to the Java language. To join PIPS you should rewrite your code to use ProcessBuilder or only pass arrays of strings to Runtime.getRuntime().exec().

Haskell The common issues section applies to the Haskell language. To join PIPS you should only ever pass a RawCommand to createProcess and never use the shell, system, runCommand or runInteractiveCommand functions from the System.Process and System.Cmd libraries.

OCaml The common issues section applies to the OCaml language. To join PIPS you should rewrite your code to use fork+exec or the create_process* wrappers instead of system, open_process, open_process_in, open_process_out and open_process_full.

Go Go allows running external processes but doesn't allow you to waste PID space by running commands in shell. Avoid explicitly running the shell though.

Rust Rust allows running external processes but doesn't allow you to waste PID space by running commands in shell. Avoid explicitly running the shell though.

Erlang The common issues section applies to the Erlang language. To join PIPS you should rewrite your code to use erlang:open_port( spawn_executable, ... , ...) instead of os:cmd or the other options to erlang:open_port.

Node.js The common issues section applies to the Node.js language. To join PIPS you should rewrite your code to use the child_process.execFile() function (or other child_process functions) instead of child_process.exec().

Julia Julia allows running external processes but doesn't allow you to waste PID space by running commands in shell. It emulates a lot of shell features instead. Avoid explicitly running the shell though.

Dart The common issues section applies to the Dart language. To join PIPS simply do not enable the runInShell parameter of the Process object.

PS Let me know if I missed something in one of these languages. You should also do most of the above to avoid shell metacharacter injection attacks that usually allow arbitrary code execution. Dear language authors, don't allow running external processes in shell, kthxbye!

16 February 2014

Craig Small: psmisc 22.21 Released

Today as it was raining and I couldn t do much gardening, psmisc version 22.21 was released. The files are located up on sourceforge at https://sourceforge.net/projects/psmisc/files/latest/download or at your favorite distro repository soon. Once again, thanks to all patch submitters, bug reports and translators for all their help in getting this out. Apologies to the translation teams for having two alpha versions. So what does psmisc 22.21 bring you? Amongst a lot of minor bug fixes it has: The Debian psmisc package should be out in the next few hours.

Mark Brown: Human factors

An issue which I always find depressing but sadly unsurprising in discussions of process with software is the frequent disregard for human elements; indeed often the goal people have in creating process is to try to control and eliminate human elements. Little thought is given to what is going to motivate people to do what s asked and if they are going to follow it at all, or in the spirit it was intended. One example I ve seen several times is the idea that some engineers work on irrelevant things and that this can be fixed by requiring every commit to be tied to the project plan or a bug so off project work is obvious. This isn t really attacking the problem so much as putting a roadblock in place to try to avert it; the real problem is normally people not communicating about what they re doing and what s important but those problems are really hard to address. Sadly what tends to happen is that people work around the roadblock and cause some collateral damage; for example devaluing the bug tracker by referencing irrelevant bugs or creating meaningless bugs solely to allow commits, while continuing to behave like they did originally. This is often worse than the original situation. This sort of issue is one of the things I appreciate most about working on Linux there s quite a bit of process but because of the way it has been evolved the incentives are usually right to make sure they are followed in the spirit in which they were intended. For example the patch submission process is essentially just best practices for making sure changes go to people who care in a form which makes it easy for them to work with it; there is a bunch of tooling around it which built on those practices (and in turn influenced the practices) but it all comes back to that basic thing of getting attention for changes and making them easy to work with. As a result people mostly do the right thing (or close enough) so everything runs smoothly. The trick is to remember to standardize and write things down when it s needed notice the good practice and spread its adoption. The key difference here seems to be if process is viewed as something to solve problems for people or if it is viewed as a way to solve problems with people. If the problem is with the people then the view starts off negative and it s perhaps unsurprising that there is little consideration of how they will react. Sometimes it s not so much that a problem is seen with people as that the people doing don t have any real interest in the process (write only timesheets often bear no relation to reality for example) but there is an assumption that they are going to just do what they re asked (but instead they for example don t fill in their time sheets or don t provide accurate information). The end result is the same, their needs don t get considered and their actions end up being counterproductive. Starting to avoid these problems is fairly straightforward take a step back and consider why the people expected to carry out the process are going to want to do so. How does it help them? How will they see it helping others? Generally what s in it for them? If these are difficult questions to answer then there may be a problem it is likely people will ignore the process or do it badly without a lot of active enforcement, but perhaps that s OK for the situation. Beware of using metrics to provide incentives, metrics are gameable and that game can cause problems without care. But do think about people; making software is all about people.

15 February 2014

Hideki Yamane: not use DEB_AUTO_UPDATE_* with cdbs, just include autotools-vars.mk

As I filed, Debian package that uses cdbs shouldn't use "DEB_AUTO_UPDATE_*", should include autotools-vars.mk file, instead.

Maybe I should file it to lintian, avoid duplicated work.

14 February 2014

Raphaël Hertzog: The Debian Administrator s Handbook, now in French and Spanish!

Cahier de l'Admin Debian WheezyBarely one and half month after the release of the Wheezy version of the Debian Administrator s Handbook, I m proud to announce that two translations have been completed: French and Spanish. And, as promised in the last liberation campaign, the French translation has been published as a paperback by Eyrolles (see the cover above). Check out the article on debian-handbook.info for more information.

2 comments Liked this article? Click here. My blog is Flattr-enabled.

Craig Small: Resetting USB devices

I m not sure if it is just a bad motherboard, cable, USB device or just bad luck, but when I reboot the computer the UPS doesn t appear. It s not even seen in lsusb and of course that makes nut-server fail which makes nut-client complain that it cannot work out the UPS status.The solution was to unplug and plug the cable in then reset nut-server and all was good. But playing with cables seems so last century, surely there was a better way? Some Googling showed up a way to Reset USB without a reboot but the directories the entry mentioned didn t exist on my computer; though there was something very close to it. Perhaps that would work? A few tweaks later and I had a working UPS monitoring cable! The changed script is below: I m not sure if it is just a bad motherboard, cable, USB device or just bad luck, but when I reboot the computer the UPS doesn t appear. It s not even seen in lsusb and of course that makes nut-server fail which makes nut-client complain that it cannot work out the UPS status.The solution was to unplug and plug the cable in then reset nut-server and all was good. But playing with cables seems so last century, surely there was a better way? Some Googling showed up a way to Reset USB without a reboot but the directories the entry mentioned didn t exist on my computer; though there was something very close to it. Perhaps that would work? A few tweaks later and I had a working UPS monitoring cable! The changed script is below:
#!/bin/sh
 
SYSXHCI=/sys/bus/pci/drivers/xhci_hcd
 
if [ "$(id -u)" != 0 ] ; then
 echo This must be run as root!
 exit 1
fi
 
if ! cd $SYSXHCI ; then
 echo Weird error. Failed to change directory to $SYSXHCI
 exit 1
fi
 
for dev_id in ????:??:??.? ; do
 printf "$ dev_id " > unbind
 printf "$ dev_id " > bind
done
Thanks to Eli for the original idea which got me onto the right path.

13 February 2014

John Goerzen: Backing up every few minutes with simplesnap

I ve written a lot lately about ZFS, and one of its very nice features is the ability to make snapshots that are lightweight, space-efficient, and don t hurt performance (unlike, say, LVM snapshots). ZFS also has zfs send and zfs receive commands that can send the content of the snapshot, or a delta between two snapshots, as a data stream similar in concept to an amped-up tar file. These can be used to, for instance, very efficiently send backups to another machine. Rather than having to stat() every single file on a filesystem as rsync has to, it sends effectively an intelligent binary delta which is also intelligent about operations such as renames. Since my last search for backup tools, I d been using BackupPC for my personal systems. But since I switched them to ZFS on Linux, I ve been wanting to try something better. There are a lot of tools out there to take ZFS snapshots and send them to another machine, and I summarized them on my wiki. I found zfSnap to work well for taking and rotating snapshots, but I didn t find anything that matched my criteria for sending them across the network. It seemed par for the course for these tools to think nothing of opening up full root access to a machine from others, whereas I would much rather lock it down with command= in authorized_keys. So I wrote my own, called simplesnap. As usual, I wrote extensive documentation for it as well, even though it is very simple to set up and use. So, with BackupPC, a backup of my workstation took almost 8 hours. (Its incremental might take as few as 3 hours) With ZFS snapshots and simplesnap, it takes 25 seconds. 25 seconds! So right now, instead of backing up once a day, I back up once an hour. There s no reason I couldn t back up every 5 minutes, in fact. The data consumes less space, is far faster to manage, and doesn t require a nightly hours-long cleanup process like BackupPC does zfs destroy on a snapshot just takes a few seconds. I use a pair of USB disks for backups, and rotate them to offsite storage periodically. They simply run ZFS atop dm-crypt (for security) and it works quite well even on those slow devices. Although ZFS doesn t do file-level dedup like BackupPC does, and the lz4 compression I ve set ZFS to use is less efficient than the gzip-like compression BackupPC uses, still the backups are more space-efficient. I am not quite sure why, but I suspect it s because there is a lot less metadata to keep track of, and perhaps also because BackupPC has to store a new copy of a file if even a byte changes, whereas ZFS can store just the changed blocks. Incidentally, I ve packaged both zfSnap and simplesnap for Debian and both are waiting in NEW.

Craig Small: Google doesn t get SPF

Someone has decided to use my email address for a spam source. They have even used google to relay it which, given Googles current policies seems like a winning idea. I keep getting emails from Google s servers with header lines like this:
X-Original-Authentication-Results: mx.google.com; spf=hardfail (google.com: domain of csmall@small.dropbear.id.au does not designate 66.80.26.66 as permitted sender)
You don t say? You mean even though my SPF records do not include some dodgy server in California, even though Google knows I don t include this in my SPF records well we will let the email go through anyhow. SPF records mean that s where my email comes from. If the record has a -all at the end of it, like mine do, then it means don t accept it from anywhere else. The hardfail means Google sees the -all and still does nothing about it.

12 February 2014

Dirk Eddelbuettel: RInside 0.2.11

A new release 0.2.11 of RInside is now on CRAN. RInside provides a set of convenience classes which facilitate embedding of R inside of C++ applications and programs, using the classes and functions provided by the Rcpp R and C++ integration package. This release, the first in fourteen months, fixes one important initialization issue created by the recent Rcpp 0.11.0 release, adds a few other changes related to that release and improves a number of small points such as new or improved examples. The NEWS extract below has more details.
Changes in RInside version 0.2.11 (2014-02-11)
  • Updated for Rcpp 0.11.0:
    • Updated initialization by assigning global environment via pointer only after R itself has been initialized with special thanks to Kevin Ushey for the fix
    • Updated DESCRIPTION with Imports: instead of Depends:
    • Added correspondiing importFrom(Rcpp, evalCpp) to NAMESPACE
    • Noted in all inst/examples/*/Makefile that Rcpp no longer requires a library argument, but left code for backwards compatibility in case 0.11.0 is not yet installed.
  • Added --vanilla --slave to default arguments for R initialization
  • Added a few more explicit #include statements in the qt example which Qt 5.1 now appears to require with thanks to Spencer Behling for the patch
  • Added new MPI example with worker functions and RInside instance, kindly contributed by Nicholas Pezolano and Martin Morgan
CRANberries also provides a short report with changes from the previous release. More information is on the RInside page. Questions, comments etc should go to the rcpp-devel mailing list off the Rcpp R-Forge page.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. Please report excessive re-aggregation in third-party for-profit settings.

Don Armstrong: Working with Org-mode: Committing Changes Everywhere

I'm a huge fan of Org-mode, and I keep all of my org-mode files in git repositories which are under myrepos control. However, because I often make lots of changes to my agenda and notes, I hate having to manually visit each individual project and make changes to it. [And it's also annoying when I forget to commit a specific change and then have to try to get my laptop and desktop back into sync.] Luckily, myrepos can easily run a command in parallel in all of the repositories! The following "update_org_files" command will update all of my org-file containing repositories in parallel:
#!/bin/bash
ORG_GREP='-e .org$ -e .org_archive$ -e .org_done$'
if [ "x$1" == "xdoit" ]; then
    if git status --porcelain -z   grep -z '^ M'   grep -zq $ORG_GREP; then
        git status --porcelain -z   grep -z '^ M'   grep -z $ORG_GREP   \
            sed -z 's/^ M//g'   \
            xargs -0 git commit -m'update org files'
        git push;
    fi; 
else
    emacsclient -n -e '(org-save-all-org-buffers)' >/dev/null 2>&1
    mr -d ~ -j5 run update_org_files doit;
fi;
An updated version of this lives in my git repository

11 February 2014

Jonathan McDowell: Choosing a new laptop

Recently I've been thinking about getting a new laptop. I have this rule that a laptop should last me at least 3 years (ideally more) and my old laptop was bought in September 2010. So for the past few months I've been trying to work out if there's something suitable on the market that is a good replacement (last time I didn't manage to find something that ticked all the boxes, but did pretty well for the price I paid). To start with I decided to track my laptops over time - largely because one of my concerns was about the size of a replacement, because I have a significant leaning towards subnotebooks. In the end the reason I decided to upgrade was for some extra CPU grunt; my old machine had a tendency to get pretty hot under any sort of load.
DateModelCPUScreenRAMStorageW (mm)H (mm)D (mm)WeightCost
1991Amstrad PPC 640DNEC V30 8MHz9" 640x200 non-backlit green LCD640k2 x 3.5" FDD45023010010kg???
August 1997Compaq Aero 4/33c486sx337.8" 640x480 CSTN LCD4MB80MB260190431.6kg???
July 2002Compaq Evo N200P-III 700MHz10.4" 1024x768 TFT192MB20GB251198201.1kg 939.99
August 2005Toshiba Portege R200Pentium M 753 1.2GHz12.1" 1024x768 TFT1280MB60GB286229201.29kg 1313.58
September 2008Asus EEE 901Atom N270 1.6GHz8.9" 1024x600 TFT2GB4GB + 16GB SSD248175231.1kg 299.99
September 2010Acer Aspire 1830TCore-i5 470UM 1.33GHz11.6" 1366x768 TFT8GB500GB284203281.4kg$699.99 (~ 480)
The EEE didn't actually replace the Toshiba, but I mention it for completeness. It was actually the only machine I moved to the US with, but after about a month of it as my primary machine I realized it wasn't an option for day to day use - though it was fantastic as a machine to throw in an overnight bag, especially when coupled with a 3G dongle. I wasn't keen on significantly increasing the size of my laptop. There are a number of decent 13" Ultrabook options out there, and I looked at a few of them, but nothing grabbed me as being worth the increase in size. Also I wanted something better than the Acer - one of the major problems was finding something smaller than 13" that had 8G RAM, let alone more. There's a significant trend towards everything soldered in for the smaller/slimmer notebooks, which makes some sense but means that the base spec had better be right. Much to my surprise the Microsoft Surface Pro 2 looked like an option. It comes with an i5-4300U processor (at least since around Christmas 2013), and the 256/512G SSD models have 8G RAM. Screen resolution is an attractive true HD (1920x1080) and the 10" display means it's smaller than the Aspire. Unfortunately the keyboard lets it down. It's fine given a flat surface, but not great if you want to support the whole thing on your lap. Which is something I tend to do with my laptop, whether that's on the sofa, or in bed, or on a bus/train. Another option was the Sony Vaio Pro 11. This is a pretty sweet laptop (I managed to get to play with one at a Sony store in the US). Super slim and light. 8GB RAM. True HD screen. However I have bad memories of the build quality of the older Vaios and the fact that there was /no/ user replaceable parts put me off - it's a safe bet that a laptop battery is going to need replaced in a 3 year lifespan. What I managed to find, and purchase, was a Dell Latitude E7240. I admit that the Dell brand made me wary - while I've not had any issue with their desktops I didn't associated their laptops as being particularly high quality. Mind you, I could say the same for Acer and I've been very pleased with the Aspire (if they'd had a more up to date model I'd have bought it). I bought the E7240 with the Core-i5 4300U (so the same as the Surface Pro 2) and True HD touch screen. It has a replaceable battery, expandable RAM (up to 16G) and the storage is an mSATA SSD. It also came with a built in 3G card. At 12.5" it's a little bigger than my old machine, but I decided that was a reasonable idea given the higher resolution. I'm typing this article on it now, having finally completed the setup and migration of the data from the old laptop to it this evening. More details once I've been using it for a little bit I think.

Dirk Eddelbuettel: RcppSMC 0.1.2

Late last week, and just before leaving to participate in this crazy thing, I managed to get a new version of RcppSMC onto CRAN. RcppSMC combines the SMCTC template classes for Sequential Monte Carlo and Particle Filters (Johansen, 2009, JSS) with the Rcpp package for R/C++ Integration (Eddelbuettel and Francois, 2011, JSS) and thereby allows for easier and more direct access from R to the computational core of the Sequential Monte Carlo algorithm. This release regroups a few minor changes we accumulated over the last few months, but was triggered by the Rcpp 0.11.0 release last week. The NEWS entry is below:
Changes in RcppSMC version 0.1.2 (2014-02-06)
  • Updated for Rcpp 0.11.0 with explicit importFrom in NAMESPACE and corresponding versioned Imports: in DESCRIPTION; also removed linking instruction from src/Makevars as no it is longer needed with this new Rcpp version
  • Addded GitHub / Travis CI support
  • Use more portable dev.new() rather than x11() in pfLinearBS.R
  • Applied some corrections to pfNonlinBS.R example
  • Converted NEWS to NEWS.Rd
Courtesy of CRANberries, there is also a diffstat report relative to the previous release. As always, more detailed information is on the RcppSMC page,

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. Please report excessive re-aggregation in third-party for-profit settings.

10 February 2014

Mario Lang: Neurofunkcasts

I have always loved Drum and Bass. In 2013 I rediscovered my love for Darkstep and Neurofunk, and found that these genres have developed quite a lot in the recent years. Some labels like Black Sun Empire and Evol Intent produce mixes/sets on a regular basis as podcasts these days. This article aggregates some neurofunk podcasts I like a lot, most recent first. Enjoy 33 hours and 57 minutes of fun with dark and energizing beats. Thanks to BSE Contrax and Evol Intent for providing such high quality sets. You can also see the Python source for the program that was used to generate this page.

9 February 2014

Neil Williams: Debian ARMMP in LAVA using iMX53

The home lab is my LAVA development environment and I ve recently got two iMX53 Quick Start Boards working with a typical LAVA master image based on a Linaro build of Linux 3.1.0 for mx5 with a Ubuntu Oneiric Ocelot 11.10 rootfs:
 3.1.0-1002-linaro-lt-mx5 (buildd@hubbard) (gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) ) #13-Ubuntu PREEMPT Fri Dec 16 01:21:07 UTC 2011
As part of my Debian work, it was clearly time to look at a current, Debian, kernel and rootfs and as I m developing and testing on Debian unstable, this would necessarily mean testing the Debian ARMMP (multi-platform) kernel which replaces the mx5 build used in Wheezy.
Linux version 3.12-1-armmp (debian-kernel@lists.debian.org) (gcc version 4.8.2 (Debian 4.8.2-10) ) #1 SMP Debian 3.12.9-1 (2014-02-01)
I will be scripting the creation of a suitable image for these tests and there are other changes planned in LAVA to make it easier to build suitable images, but it is useful to document just how I worked out how to build the first image. Manual build steps First, I ve already discovered that the u-boot on the iMX53 doesn t like ext4, so the first step was to prepare an ext3 filesystem for the image. With a SATA drive attached, it was also much better to use that than the SD card, at least for generating the image. I m also doing this natively, so I am working inside the booted master image. This is fine as the master is designed to manipulate test images, so the only package I needed to install on the LAVA master image was debootstrap. I had an empty SATA drive to play with for these tests, so first prepare an ext3 filesystem:
# mkfs.ext3 /dev/sda1
# mkdir /mnt/sata
# mount /dev/sda1 /mnt/sata
# mkdir /mnt/sata/chroots/
Start the debootstrap:
# apt-get update
# apt-get install debootstrap
# debootstrap --arch=armhf --include=linux-image-armmp \
 --verbose unstable \
 /mnt/sata/chroots/unstable-armhf http://ftp.uk.debian.org/debian
Various actions in this chroot will need proc, so mount it here:
# chroot /mnt/sata/chroots/unstable-armhf
# mount proc -t proc /proc
# mount devpts -t devpts /dev/pts
# exit
You may also have to edit the apt sources the LAVA master image doesn t have editors installed, so either use echo or download an edited file. I m using:
deb http://ftp.uk.debian.org/debian sid main
flash-kernel needs changes For the initial tests, I ve got to get this image to boot directly from u-boot, so flash-kernel is going to be needed inside the chroot and to get the iMX53 to work with the ARMMP kernel and Device Tree, flash-kernel will need an update which will mean a patch:
# chroot /mnt/sata/chroots/unstable-armhf
# apt-get update
# apt-get install patch flash-kernel
# cp /usr/share/flash-kernel/db/all.db /home
# cd /home
# patch -p2
The patch itself goes through a couple of iterations. Initially, it is enough to use:
 Machine: Freescale MX53 LOCO Board
-Kernel-Flavors: mx5
+Kernel-Flavors: armmp
+DTB-Id: imx53-qsb.dtb
+DTB-Append: yes
Later, once the device has booted with the ARMMP kernel, the Machine Id can be updated to distinguish it from the mx5 flavour (from /proc/cpuinfo) and use the model name from the Device Tree (/proc/device-tree/model):
diff --git a/db/all.db b/db/all.db
index fab3407..41f6c78 100644
--- a/db/all.db
+++ b/db/all.db
@@ -62,6 +62,18 @@ U-Boot-Initrd-Address: 0x00800000
 Required-Packages: u-boot-tools
 Bootloader-Sets-Incorrect-Root: yes
 
+Machine: Freescale i.MX53 Quick Start Board
+Kernel-Flavors: armmp
+DTB-Id: imx53-qsb.dtb
+DTB-Append-From: 3.12
+Boot-DTB-Path: /boot/dtb
+U-Boot-Kernel-Address: 0x70008000
+U-Boot-Initrd-Address: 0x0
+Boot-Kernel-Path: /boot/uImage
+Boot-Initrd-Path: /boot/uInitrd
+Required-Packages: u-boot-tools
+Bootloader-Sets-Incorrect-Root: no
+
 Machine: Freescale MX53 LOCO Board
 Kernel-Flavors: mx5
 U-Boot-Kernel-Address: 0x70008000
(I will be filing this patch in a bug report against flash-kernel soon.) With that patched, update and run flash-kernel:
# mv all.db /usr/share/flash-kernel/db/all.db
# flash-kernel
flash-kernel: installing version 3.12-1-armmp
Generating kernel u-boot image... done.
Taking backup of uImage.
Installing new uImage.
Generating initramfs u-boot image... done.
Taking backup of uInitrd.
Installing new uInitrd.
Installing new dtb.
# exit
LAVA overlays This will be a LAVA test image and it needs an overlay if you want a vanilla image, set up a passwd inside the chroot instead.
# cd /mnt/sata/chroots/unstable-armhf/
# wget --no-check-certificate https://launchpad.net/~linaro-maintainers/+archive/overlay/+files/linaro-overlay-minimal_1112.2_all.deb
# wget --no-check-certificate https://launchpad.net/~linaro-maintainers/+archive/overlay/+files/linaro-overlay_1112.2_all.deb
# chroot /mnt/sata/chroots/unstable-armhf/
# dpkg -i linaro-overlay-minimal_1112.2_all.deb linaro-overlay_1112.2_all.deb
# rm linaro-overlay-minimal_1112.2_all.deb linaro-overlay_1112.2_all.deb
# exit
Changes to allow the chroot to boot Now the chroot needs setting up as a boot image:
# chroot /mnt/sata/chroots/unstable-armhf/
# echo T0:23:respawn:/sbin/getty -L ttymxc0 115200 vt102 >> ./etc/inittab
# echo auto lo eth0 > ./etc/network/interfaces.d/mx53loco
# echo iface lo inet loopback >> ./etc/network/interfaces.d/mx53loco
# echo iface eth0 inet dhcp >> ./etc/network/interfaces.d/mx53loco
# apt-get clean
# umount /dev/pts
# umount /proc
# exit
Partitioning as a LAVA test image This would be enough as a single partition test image but, currently, LAVA expects a much more hard-wired image. Depending on the history of the device and the need for LAVA to be able to put fresh kernel builds together with a known rootfs, LAVA has used a separate /boot and / partition in the test image for nearly all boards. Standard LAVA test images for many boards (like the iMX53) also have a small unallocated space at the start of the SD card, so until I can get LAVA upstream to handle test images of arbitrary design, I m adapting the image to suit the expectations inside LAVA. Yes, I know but it s better to get something working before spending time fixing things to make it work better. It will be fixed, in time. So I needed to separate out the /boot contents from the rest of the rootfs whilst keeping the chroot itself in a state which I can easily update and use to create other images.
# cd /mnt/sata/chroots/unstable-armhf/boot/
# tar -czf ../../boot.tar.gz ./*
# cd ..
# tar -czf ../root.tar.gz ./*
Now the test image file and its partitions:
# dd if=/dev/zero of=/mnt/sata/images/empty/debian.img bs=1M count=1024
# cp /mnt/sata/images/empty/debian.img /mnt/sata/images/debian-unstable-armhf-armmp.img
# losetup /dev/loop0 /mnt/sata/images/debian-unstable-armhf-armmp.img
# parted /dev/loop0 -s unit mb mktable msdos
# parted /dev/loop0 -s unit mb mkpart primary 1 10
# parted /dev/loop0 -s unit mb mkpart primary 11 110
# parted /dev/loop0 -s unit mb mkpart primary 111 1024
I did make the mistake of using kpartx at this stage but there are many areas of confusion when translating the kpartx output to offsets for mount when parted is easier:
# parted /dev/loop0 unit B -s print
Model:  (file)
Disk /dev/loop0: 1073741824B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number  Start       End          Size        Type     File system  Flags
 1      1048576B    10485759B    9437184B    primary
 2      10485760B   110100479B   99614720B   primary
 3      110100480B  1024458751B  914358272B  primary
Use the Start numbers and use losetup to create the loop devices for each
partition
# losetup -o 10485760 /dev/loop1 /dev/loop0
# losetup -o 110100480 /dev/loop2 /dev/loop0
# mkfs.vfat /dev/loop1
# mkfs.ext3 /dev/loop2
Now clean up the loop mountpoints:
# losetup -d /dev/loop2
# losetup -d /dev/loop1
# losetup -d /dev/loop0
# losetup -a
losetup -a should return nothing. If it doesn t, investigate the contents of /dev/mapper and use dmsetup remove until losetup -a does report empty. Otherwise the subsequent stages will fail. Now deploy the /boot contents into the empty image:
# mount -oloop,offset=10485760 /mnt/sata/images/debian-unstable-armhf-armmp.img /mnt/boot/
# pushd /mnt/boot/
# tar -xzf /mnt/sata/chroots/boot.tar.gz
# popd
# sync
# umount /mnt/boot/
and the / contents (removing the duplicate ./boot contents)
# mount -oloop,offset=110100480 /mnt/sata/images/debian-unstable-armhf-armmp.img /mnt/root/
# pushd /mnt/root
# tar -xzf /mnt/sata/chroots/root.tar.gz
# rm ./boot/*
# popd
# sync
# umount /mnt/root
Check the image
# mount -oloop,offset=10485760 debian-unstable-armhf-armmp.img /mnt/boot
# ls /mnt/boot
config-3.12-1-armmp  initrd.img-3.12-1-armmp  System.map-3.12-1-armmp  uImage  uInitrd  vmlinuz-3.12-1-armmp
# umount /mnt/boot
# mount -oloop,offset=110100480 debian-unstable-armhf-armmp.img /mnt/root
# ls /mnt/root
bin  boot  dev  etc  home  initrd.img  lib  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  vmlinuz
# ls /mnt/root/bin/auto-serial-console
/mnt/root/bin/auto-serial-console
# umount /mnt/root
# md5sum debian-unstable-armhf-armmp.img
Downloads Yes, I have put that file online, if you are interested. Do read the readme first though. Getting the image off the device
# ip a
# python -m SimpleHTTPServer 80 2>/dev/null
then wget (just http://, IP address / and the filename), md5sum , finish with Ctrl-C. Depending on setup, it may be quicker to transfer the uncompressed
file over a LAN than to let the device compress it. Your main machine
will do the compression much faster, even with a larger download. (It also helps to not compress the image on the device, you can
test the mount offsets more easily and do check that the image
can be mounted with the offsets from parted.) Results
# cat /proc/cpuinfo
processor	: 0
model name	: ARMv7 Processor rev 5 (v7l)
Features	: swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x2
CPU part	: 0xc08
CPU revision	: 5
Hardware	: Freescale i.MX53 (Device Tree Support)
Revision	: 0000
Serial		: 0000000000000000
# uname -a
Linux imx53-02 3.12-1-armmp #1 SMP Debian 3.12.9-1 (2014-02-01) armv7l GNU/Linux
# lsb_release -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux unstable (sid)
Release:	unstable
Codename:	sid
Next! Yes, there is a lot to do from here on. Then there is the whole issue of actually making this multi-platform. After all, it is far from ideal that a multi-platform kernel package has to have platform-specific operations using flash-kernel at each update. So Grub on ARM is going to be on the list of things to investigate .

8 February 2014

Sam Hartman: IETF Takes on Challenge of Internet Monitoring

At IETF 88, we held a plenary discussion of how we could harden the Internet against ongoing monitoring and survalence. There were no significant surprises in what people said about monitoring. So, we had an opportunity to focus on what the IETF as a standards organization responsible for technical standards that drive the Internet can do about this problem. I think we made amazing progress. The IETF works by consensus. We discuss issues, and see if there s some position that can gain a rough consensus of the participants in the discussion. After a couple of hours of discussion, Russ Housley asked several consensus questions. The sense of the room is that we should treat these incidents of monitoring as an attack and include them in the threats we try and counter with security features in our protocols. The room believes that encryption, even without authentication has value in fighting these attacks. There was support for the idea of end-to-end encryption is valuable even when there are middle boxes. IETF decisions made in meetings are confirmed on public mailing lists, so the sense of the room is not final. Also, note that I did not capture the exact wording of the questions that were posed. This is huge. There is very strong organizational agreement that we re going to take work in this space as seriously. Now that we ve decided pervasive monitoring is an attack, anyone can ask how a proposed protocol (or change to a protocol) counters that attack. If it doesn t handle the attack and there is a way to address the attack, then we will be in a stronger position arguing the threat could be addressed. In addition, the commitment to encryption providing value without authentication will be useful in providing privacy and minimizing fingerprinting by passive attackers. The IETF is only one part of the solution. We can work on the standards that describe how systems interact. However, implementations, policy makers, operators and users will also play a role in securing the Internet against pervasive attacks.

Mario Lang: boost::python and boost::variant

I have unsuccessfully tried to find a solution for the following problem on the internet several times. Now that I have come at least closer to a usable approach, I thought I'd document what I have found so that others trying to achieve a similar thing can use this as a starting point. Boost.Python offers a very nice and flexible way to interface C++ data types with Python. With just a few lines of code, and the proper linker flags, you get a Python importable shared object from your C++ compiler. This can be very productive. However, there is one aspect of C++ data types that I couldn't figure out how to interface with Python, which are C++ discriminated unions, or more specifically, heterogeneous containers. While Python has no problems with containers containing objects of different types, C++ does not make this very easy by default. Usually the problem is solved with a container of pointers to a base class, and various subclasses with virtual functions. However, this approach is not always practical, especially if the different types of objects in an heterogeneous container dont have many things in common. This is where discriminated unions come to the rescue. They basically behave like a normal union in C, but have an additional field which indicates the type of object currently stored in the union. Boost.Variant does exactly that, with a nice visitor interface added on top of it.
Heterogeneous containers in C++ If we put the boost::variant<> template inside a STL container like std::vector<>, the result is a heterogeneous container. For the purpose of illustration, lets implement such a container. The example below is deliberately simple. In reality, the various types allowed in your variant will probably have more fields then just one.
#include <boost/variant.hpp>
#include <vector>
struct a   int x;  ;
struct b   std::string y;  ;
typedef boost::variant<a, b> variant;
typedef std::vector<variant> vector;
To ease creation of these two types of objects, we are going to write a few factory functions. We are going to wrap them in Python later on.
variant make_variant()   return variant();  
vector make_vector()   return vector a(), b(), a() ;  
Boost.Python Now lets create a Python module which exports the above functionality to Python.
#include <boost/python/class.hpp>
#include <boost/python/def.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/init.hpp>
#include <boost/python/module.hpp>
#include <boost/python/object.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
vector_indexing_suite apparently needs operator== defined on the value_type of the container. In our case, this is our boost::variant<a, b> type. Luckily, boost::variant<> already provides operator==. However, that operator== relies on operator== being defined for the underlying types. Since equality comparison is probably useful for other things as well, lets just create operator== for our two classes a and b.
bool operator==(a const &lhs, a const &rhs)   return lhs.x == rhs.x;  
bool operator==(b const &lhs, b const &rhs)   return lhs.y == rhs.y;  
Convert a boost::variant<> to PyObject * Boost.Python needs a way to convert our discriminated union to a Python object. This code relies on Python class definitions being present for all underlying variant types. We will define them later.
struct variant_to_object : boost::static_visitor<PyObject *>  
  static result_type convert(variant const &v)  
    return apply_visitor(variant_to_object(), v);
   
  template<typename T>
  result_type operator()(T const &t) const  
    return boost::python::incref(boost::python::object(t).ptr());
   
 ;
And finally, lets create our Python module.
BOOST_PYTHON_MODULE(bpv)  
  using namespace boost::python;
  class_<a>("a", init<a>()).def(init<>()).def_readwrite("x", &a::x);
  class_<b>("b", init<b>()).def(init<>()).def_readwrite("y", &b::y);
  to_python_converter<variant, variant_to_object>();
  implicitly_convertible<a, variant>();
  implicitly_convertible<b, variant>();
  def("make_variant", make_variant);
  class_<vector>("vector").def(vector_indexing_suite<vector, true>());
  def("make_vector", make_vector);
 
Compiling Lets create a shared object for Python.
$ g++ -std=c++11 -fPIC -shared $(python-config --includes) -o bpv.so file.cpp -lboost_python
Running We can load the module into Python and see what it does.
>>> import bpv
>>> variant=bpv.make_variant()
>>> variant
<bpv.a object at 0x7f06bb2130c0>
>>> variant.x
0
>>> variant.x=2
>>> variant.x
2
Nice. We can access the underlying type, and even modify it. Lets see how our heterogeneous container wrapping code behaves.
>>> vector=bpv.make_vector()
>>> vector
<bpv.vector object at 0x7f20693289d0>
>>> len(vector)
3
>>> list(vector)
[<bpv.a object at 0x7f20693190c0>, <bpv.b object at 0x7f20693193d0>, <bpv.a object at 0x7f2069319440>]
So far, so good. This will at least make it possible to convert heterogeneous containers from C++ to Python, which was my initial goal. Unfortunately, contained objects are not treated as references. Whenever retrieved, we get a copy. So in-place modification does not work.
>>> vector[0].x
0
>>> vector[0].x=2
>>> vector[0].x
0
However, we can override an existing element with a modified copy.
>>> e0=vector[0]
>>> type(e0)
<class 'bpv.a'>
>>> e0.x = 2
>>> vector[0] = e0
>>> vector[0].x
2
And we can also use the append and extend methods of Python containers.
>>> len(vector)
3
>>> vector.extend(vector)
>>> vector.append(bpv.a())
>>> len(vector)
7
>>> len(filter(lambda x: type(x)==bpv.b, vector))
2
>>> len(filter(lambda x: type(x)==bpv.a, vector))
5
>>> map(lambda x: x.x, filter(lambda x: type(x)==bpv.a, vector))
[2, 0, 2, 0, 0]
All that is missing for a perfect world is reference semantics for container elements. If anyone has a hint on how to achieve this, please let me know.

John Goerzen: Migrated from Hetzner to OVH hosting

Since August 2011, my sites such as complete.org have been running on a Xen-backed virtual private server (VPS) at Hetzner Online, based in Germany. I had what they called their VQ19 package, which included 2GB RAM, 80GB HDD, 100Mb NIC and 4TB transfer. Unlike many other VPS hosts, I never had performance problems. However, I did sometimes have hardware problems with the host, and it could take hours to resolve. Their tech support only works business hours German time, which was also a problem. Meanwhile, OVH, a large European hosting company, recently opened a datacenter in Canada. Although they no longer offer their value-line Kimsufi dedicated servers there starting at $11.50/mo they do offer their midrange SoYouStart servers there. $50/mo gets a person a 4-core 3.2GHz Xeon server with 32GB RAM, 2x2TB SATA HDD, 200Mbps bandwidth. Not bad at all! The Kimsufi options are still good for lower-end needs as well. I signed up for one of the SoYouStart servers. I ve been pleased with my choice to migrate, and at the possibilities that having hardware like that at my disposal open up, but it is not without its downside. The primary downside is lack of any kind of KVM console. If the server doesn t boot, I can t see the Grub error message (or whatever) behind it. They do provide hardware support and automatic technician dispatching when the server isn t pingable, but they state they have no KVM access at all. They support many OS flavors, and have a premade image for them, but there is no using a custom ISO to install; if you want ZFS on Linux, for instance, you can t very easily build it into root. My server was promised within 72 hours, but delivered much quicker: within about 1. I had two times they said they had to replace a motherboard within the first day; once they did it in 30 minutes, and the other took them 2.5 hours for some reason. They do have phone support, which answers almost immediately, but the people there are not the people actually in the datacenter. It was frustrating with a server down for hours and nobody really commenting on what was going on. The server performs quite well, and after the initial issues, I ve been happy. I was initially planning an all-ZFS installation. SoYouStart does offer a rescue environment, but it doesn t support ZFS, so I figured I better stick with an ext4 root at least. The default Debian install uses RAID1 on md-raid, with a 20GB root partition and the rest of the 2TB drive in /home, and then a swap partition on each drive (mysteriously NOT in the RAID!) So I broke the mirror on /home and converted those into the two legs of a mirrored vdev for a zpool. I run all of the real work inside KVM VMs, so that should minimize the number of times I have to do anything to the root filesystem that could cause trouble. SoYouStart includes 100GB of space on a separate FTP server for backup purposes. I have scripts that upload nightly tarballs of the root filesystem, plus full zfs send streams of everything else. Every hour, it uploads an incremental zfs send stream as well. This all works quite nicely; even if the machine is a complete loss, I d never lose more than an hour s work, and could restore it completely from a rescue environment. Very nice! I ll write more in a few days about the ZFS setup I m using, and some KVM discoveries as well.

7 February 2014

Jo Shields: Dear Fake Debian Developers, shoo.

Another post about the Valve/Collabora free games thing. This time, the bad bit people trying to scam free games from us. Before I start, I want to make one thing clear there are people who have requested keys who don t meet the criteria, but are honest and legitimate in their requests. This blogspam is not about them at all. If you re in that category, you re not being complained about. So. Some numbers. At time of writing, I ve assigned keys to 279 Debian Developers or Debian Maintainers almost 25% of the total eligible pool of about 1200. I ve denied 22 requests. Of these 10 were polite requests from people who didn t meet the conditions stated (e.g. Ubuntu developers rather than Debian). These folks weren t at all a problem for us, and I explained politely that they didn t meet the terms we had agreed at the time with Valve. No problem at all with those folks. Next, we have the chancers, 7 of them, who pretended to be eligible when they clearly weren t. For example, two people sent me signed requests pointing to their entry on the Debian New Maintainers page when challenged over the key not being in the keyring. The NM page showed that they had registered as non-uploading Debian Contributors a couple of hours previously. A few just claimed I am a DD, here is my signature when they weren t DDs at all. Those requests were also binned.
Papers, Please screenshot - denied entry application

DENIED

And then we move onto the final category. These people tried identity theft, but did a terrible job of it. There were 5 people in this category:
From: Xxxxxxxx Xxxxxx <xxxxxxxx.xxxxxx@ieee.org>
Subject: free subscription to Debian Developer
8217 A205 5E57 043B 2883 054E 7F55 BB12 A40F 862E
This is not a signature, it s a fingerprint. Amusingly, it s not the fingerprint for the person who sent my mail, but that of Neil McGovern a co-worker at Collabora. Neil assured me he knew how to sign a mail properly, so I shitcanned that entry.
From: "Xxxxx, Xxxxxxxxx" <x.xxxxx@bbw-bremen.de>
Subject: Incoming!
Hey dude,
I want to have the redemption code you are offering for the Valve Games
mQGiBEVhrscRBAD4M5+qxhZUD67PIz0JeoJ0vB0hsLE6QPV144PLjLZOzHbl4H3N
...snip...
Lz8An1TEmmq7fltTpQ+Y1oWhnE8WhVeQAKCzh3MBoNd4AIGHcVDzv0N0k+bKZQ=3D=3D
=3Du/4R
Wat? Learn to GPG!
From: Xxxxxx-Xxxx Le Xxxxxxx Xxxx <xx.xxxxxxxxx@gmail.com>
Subject: pass steam
Hey me voila
Merci beaucoup
valve
2069 1DFC C2C9 8C47 9529 84EE 0001 8C22 381A 7594
Like the first one, a fingerprint. This one is for S bastien Villemot. Don t scammers know how to GPG sign?
From: "Xxxxxxxxx Xxxxxxx" <xxxxxxxx@web.de>
Subject: thanks /DD/Steam gifts us finally something back
0x6864730DF095E5E4
Yet again, a fingerprint. This one is for Marco Nenciarini. I found this request particularly offensive due to the subject line the haughty tone from an identity thief struck me as astonishingly impertinent. Still, when will scammers learn to GPG?
From: Sven Hoexter <svenhoexter@gmail.com>
Subject: Valve produced games
I'm would like to get the valve produced games
My keyring: 0xA6DC24D9DA2493D1 Sven Hoexter <hoexter> sig:6
Easily the best scam effort, since this is the only one which both a) registered an email address under the name of a DD, and b) used a fingerprint which actually corresponds to that human. Sadly for the scammer, I m a suspicious kind of person, so my instinct was to verify the claim via IRC.
31-01-2014 16:52:48 > directhex: Hoaxter, have you started using gmail without updating your GPG key? (note: significantly more likely is someone trying to steal your identity a little to steal valve keys from collabora)
31-01-2014 16:54:51 < Hoaxter!~sh@duckpond6.stormbind.net: directhex: I do not use any Google services and did not change my key
So yeah. Nice try, scammer. I m not listing, in all of this, the mails which Neil received from people who didn t actually read his mail to d-d-a. I m also not listing a story which I ve only heard second ha actually no, this one is too good not to share. Someone went onto db.debian.org, did a search for every DD in France, and emailed every Jabber JID (since they look like email addresses) asking them to forward unwanted keys. All in all, the number of evildoers is quite low, relative to the number of legitimate claims 12 baddies to 279 legitimate keys issued. But still, this is why the whole key issuing thing has been taking me so long and why I have the convoluted signature-based validation system in place. Enjoy your keys, all 279 of you (or more by the time some of you read this). The offer has no explicit expiry on it Valve will keep issuing keys as long as there is reason to, and Collabora will continue to administer their allocation as long as they remain our clients. It s a joint gift to the community thousands of dollars worth of games from Valve, and a significant amount of my time to administer them from Collabora.

Next.

Previous.