Mar 232018

A colleague of mine asked me today, how this could be:

Given this exception handler:

  // some code that calls methods
  on e: Exception do

How could e be nil? (and e.Message result in an Access Violation?)

It turned out to be an error in one of the methods that were called:

if SomeCondition then
  raise Exception('some error message');

Can you spot the problem here? For whatever reason the .Create call is missing! So instead of an exception object raise was working on a string typecasted to exception.
Changing it as follows fixed the error:

if SomeCondition then
  raise Exception.Create('some error message');

We did a grep search for “raise Exception(” in our code base and found 4 more cases where this problem existed. 4 bugs less, probably still quite a few to go.

But even worse: Greping for “raise e[a-z]*(” turned up two more cases. One in my own dzlib (unit u_dzVclUtils), another in the jcl (That one has already been fixed, my copy is a bit dated.).

In the comments to the corresponding Google+ post, David Hoyle pointed out another common mistake regarding exceptions: Forgetting to actually raise them:

if SomeCondition then
  Exception.Create('some error message');

So, I did a grep for ” e[a-z]*\.Create\(” and found several, one in the (old) SynEdit version used in GExperts, several in Indy 10 and JVCL (old versions again) and one in System.JSON.Types of the current Delphi 10.2.3 RTL (RSP-20192). None in my own code this time. 🙂

Mar 212018

Parted is a flexible tool for working with partition tables under Linux. Unfortunately it sometimes seems rather stupid. For example when you create a new partition you may get the warning “The resulting partition is not properly aligned for best performance”. It could then of course proceed to suggest the proper alignment, but it doesn’t, so in theory you are left to figure out the right alignment yourself.

Fortunately there is a simple way to get parted to do that for you anyway, as described e.g. in this blogpost by Jari Turkia under “Attempt 4: The simple way”: Use percentages.

mkpart /dev/somedevice ext4 0% 100%

It took me a while to find that one again, so I made a blog post of it, so I can easily come back to it when I need it again.

Mar 142018

In theory it is easy to detect when the user plugs in a USB device to a Linux computer and notify him what was detected. In practice it’s still easy as long as you know how to do it.

First thing to do is add a file to


The file name should follow the convention of NN-SomeDescriptiveName.rules, where NN is a two digit number. In our case it should be one of the last scripts to execute since by then all of the initialization by other scripts should be done and also printing the name to the console is not the most important part of the initialization. So let’s go with


That file defines what kind of events we are interested in. In this case, we are interested in the connection of a USB hard drive, so it looks like this:

ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb", KERNEL=="sd?1" RUN+="/usr/local/bin/"

Note that the first 4 entries are conditions which are using C syntax, so there must be a double equal sign (Took me nearly an hour to find out that I missed one, debugging these events is not easy.).

  • ACTION==”add”: We want to know when a new device is being added
  • SUBSYSTEM==”block”: The device must be a block device (e.g. hard disk)
  • SUBSYSTEMS==”usb”: And it must be connected via USB
  • KERNEL=”sd?1″: And the device name must match /dev/sd?1, which means it must be a partition on a disk that is accessed as SCSI (basically everything nowadays)

If these conditions are met the last directive will be executed. It’s also C like, it appends something to the RUN variable, in our case we want to call the script


Once you have created this file, make sure to let udev know that you did that.

sudo /etc/init.d/udev restart

should work on most Linux distributions.

The first script should be simple to check whether it is actually being called.

exit 15

All it does is exiting with an exit code 15. This will show up in /var/log/syslog so we can check whether our script has been executed at all. Don’t forget to make it executable with

sudo chmod u+x /usr/local/bin/

Once we are sure it does, we change it to do the real work:


DevLabel=${temp%% *}
temp="${DEVNAME} (${DevLabel}) connected"
echo $temp | wall
echo $temp > /dev/console
exit 0

udev passes information about the device using many environment parameters. In our case we only want to know the device name and the partition label.

The device name is easy, it’s being passed in $DEVNAME. The device label is trickier. I only found it in $DEVLINKS which contains a list of /dev/* entries that link to the device, one of them being /dev/disk/by-label/[partition-label] which is the label of the partition of the device (and our device is the first partition, see the KERNEL filter above).

So first, we use a bit of bash magic got extract the label from $DEVLINKS, then we create the string $temp we want to write and last we send it to all logged on users using the wall command and for good measure to the local console.

Finally, we exit the script with exit code 0.

That’s it. Easy, when you know how to do it. Hard, if you have to find out about all the parts using Google (which was unhelpful as always and “found” lots of unrelated stuff even when I put the words I wanted it to look for in quotation marks. 🙁 )

Some caveats:

  • Scripts called by udev are restricted in what they are allowed to do. E.g. they usually cannot write to /tmp. It took me a while to figure that out, this answer on helped.
  • Also, sending an email didn’t work for me. Probably another restriction.
  • Writing to the system console is done by writing to /dev/console. (Google was only moderately helpful here again.)
Mar 012018

Sometimes you need a large file for testing purposes or just to take up space that should not be available on the file system.

There are several options on how to generate such a file on Linux:

  • The traditional method is using dd, setting if (in file) to either /dev/null or to /dev/random.
  • A more modern method is using truncate, which generates sparse files, which may be or may not be what you want.
  • An alternative modern method is using fallocate, which does not generate sparse files

Let’s say you want to create a 500 GibiByte file:

Using dd and filling it with 0 is done like this:

 dd if=/dev/zero of=500gbfile bs=500M count=1024

Using truncate (which will be read as a file containing 0s but not actually use that much space) is done like this:

truncate -s 500G 500gbfile

Using fallocate (filling it with 0s and actually allocating the space) is done like this:

fallocate -l 500G 500gbfile

Source: This article on StackOverflow.

Feb 222018

Keeping track of changes in the Linux configuration can be a chore but sometimes it is vital to know what was changed. As a software developer I am used to using version control systems for source code, so why not use one for configuration files?

Enter etckeeper a tool that does exactly that: It tracks changes to files in /etc (including access rights) in a git repository (alternatively it can be configured to use Mercurial, Bazar or Darcs, unfortunately svn is not supported).

It hooks into apt to automatically track changes made by updates. Manual updates can be committed explicitly, but there is also a daily cron job that does it automatically.

Feb 212018

.. make lemonade. Yes, that would be nice, but unfortunately we are not talking about life and lemons here.

Today a coworker had a problem with Mozilla Thunderbird: She could no longer open attachments sent to her. Saving these attachments resulted in 0 byte files.

This nearly drove me nuts:

The email source looked fine to me. When she forwarded these emails to me, I could open and save these attachments fine, so it wasn’t the emails.

Also, attachments sent to a different account in her Thunderbird worked fine. So it wasn’t Thunderbird or the virus scanner or some kind of access rights problem.

As a test, I installed a new Thunderbird Portable for her account, guess what? It could also open these attachments.

I eventually solved the problem by removing that apparently defective account from Thunderbird and adding it again. Everything started to work normal.

There are days when you just have to accept that you don’t understand why it works now and why it didn’t work before. I definitely hate it when that happens.

Feb 172018

UPDATE: The problem was that I was using Delphi 10.2.2 build 1978. Apparently I have missed an update in December 2017 to build 2004. I have downloaded and installed the new version, and now the patch worked fine.

I hereby apologize for being stupid, because it clearly says in the description:

This patch for RAD Studio 10.2.2 (build 2004 — it won’t work on build 1978) resolves some compatibility issues in the RTL and fixes a problem with Android animations. It is designed to be installed only on top of an existing RAD Studio 10.2.2 Tokyo installation.

(emphasis mine)

I was so sure to be running the latest version that I didn’t even check. Sorry about causing so much fuss.

I’ll leave the rest of the blog post unchanged just in case anybody is googling for some of the key words and to remind me to check first and complain later.

After I reported the problem with the Delphi 10.2.2 February 2018 Patch, Embarcadero first removed the download and has now released a new installer. Unfortunately this new patch might have solved some other problems, but it didn’t solve mine. I did a complete uninstall of Delphi 10.2.2 (I even removed all directories and files that the uninstall left behind) and a new installation from my DVD followed by applying the new patch. I could still not compile GExperts and the simple test program I described in the steps for the bug report did not compile either. (Guess what: Embarcadero apparently never actually tried to reproduce my problem, but the ticket was closed anyway.). I don’t know what exactly they think they fixed, but they didn’t fix the problem I reported which is:

RAD Studio 10.2.2 Tokyo February 2018 Patch breaks “Link with rutime packages”

  1. Create a new VCL project
  2. Open project options
  3. Select Packages -> Runtime Packages
  4. Set “Link with runtime packages” to true
  5. Close dialog with OK
  6. Compile the project
  7. -> Error

Today I tried to find out what the problem was and how to fix it. It turned out to be actually quite simple:

They updated the packages rtl.bpl and fmx.bpl together with their corresponding .dcp files. Since the .dcp files contain some versioning information the packages that use these packages (e.g. vcl.bpl which uses rtl.bpl) were no longer compatible with the new packages and the compiler complained about this.

So, the fix for this would be to recompile all the packages depending on rtl.bpl and fmx.bpl, but since I don’t have all the sources required for that, I couldn’t do that (but Embarcadero should).

What I did instead was replacing the .dcp files in libs\win32\debug and libs\win32\release with the .bak files that the Patch created. Afterwards, GExperts compiled again. And since probably the interface of the bpl files didn’t change, I don’t expect any problems. But of course, I can’t guarantee this. So, if you follow my example, you might still run into problems and, No, I won’t fix your computer. 😉

Feb 162018

Let’s say you have a directory of backups looking like this:

 \-> user1\
          \-> [date1]_[time1]
          \-> [date2]_[time2]
          \-> some more sub directories with date and time in the name
 \-> user2\
          \-> [date3]_[time3]
          \-> [date4]_[time4]
          \-> some more sub directories with date and time in the name
 \-> some more user sub directories

Where [dateN] is the date of the backup starting with a 4 digit year, followed by a two digit month and day, e.g. 20160531.

Now, you run out of disk space and you want to delete the oldest backups, let’s say those from 2015 and 2016. How do you do that?

You could, of course write a program, or, if you are more of a scripting person, a script, that

  1. recurses through the first level of sub directories
  2. looks for sub directories starting with 2015 or 2016
  3. deletes these recursively

Or, you could combine the shell commands find and rm:

find . -maxdepth 2 -mindepth 2 -type d -name "2015*" -exec rm -r {} \;
find . -maxdepth 2 -mindepth 2 -type d -name "2016*" -exec rm -r {} \;

find searches for files and directories that match the given query and does something for each file found, which in this case is call the command rm. But lets have a look at the specific commands above. It restricts the results by the following conditions:

  • “.” (a dot) means: Start in the current directory
  • “-maxdepth 2” means: Recurse sub directories down to two levels maximum
  • “-mindepth 2” means: Recurse sub directories down two levels minimum
  • “-type d” means: Only process directories (not files or devices or links)
  • “-name “2015*”” means: Process only entries whose name matches the shell wildcard “2015*”, so starts with “2015”
  • “-exec rm -r {} \;” means: For each entry execute the command “rm -r {}”, where {} is a place holder for the current entry name.

If you want to test the find command without risking to lose data, leave out the -exec part at the end. The find command will then simply output the entries it finds.

find . -maxdepth 2 -mindepth 2 -type d -name "2015*"
Feb 142018

IMAPcopy is a tool written by Armin Diehl. Its purpose is to copy emails from one IMAP server to another (or from one IMAP account to another) including the folder hierarchy and even the read status. It’s a command line program written in Delphi and fpc.

Since I am currently migrating a mail server I had use for such a tool and this one was the only one that did not require Java or dotNET, so I tried it. Of course, being a software developer, I found it lacking and improved it.

So, what did I improve?

Mostly one part: I did not like the fact that I had to specify the passwords of the IMAP accounts in the configuration file, so I added an option to specify “?” as the password and the tool would then let me input it at run time. I also added colouring to the the output, so it is easier to spot warnings and errors. And last but not least, I fixed a few typos in the messages.

It’s GPL code, so I’m required to give the source code to everybody to whom I give the executable. I could, of course, simply use the improved version and not tell anybody about it, so I could keep the source code “secret”, but on the other hand, why should I?

So, here is the source code. It compiles with Delphi 2007, I have not tested any other versions and I am sure it won’t compile with fpc (yes, that’s no improvement, but I don’t care).

It also needs a a Delphi port of the Borland CRT unit. I used the one released 1998 by Sergey Perevoznik, which is NOT licensed under the GPL. I have no idea where I got it from and I am not sure about the copyright since it looks like it started out as a copy of Borland’s source code. So I am not going to provide it here, sorry. But you might have a look at Embarcadero’s CodeCentral for alternatives.

Feb 112018

Note to self: In Lazarus Win64 there is no floating point type Extended, it’s mapped to Double. So, overloading something like:

function TryStr2Float(const _s: string; out _flt: Extended; _DecSeparator: Char = '.'): Boolean; overload;
function TryStr2Float(const _s: string; out _flt: Double; _DecSeparator: Char = '.'): Boolean; overload;
function TryStr2Float(const _s: string; out _flt: Single; _DecSeparator: Char = '.'): Boolean; overload;

will not compile.

Workaround: Add an {$IFNDEF Win64} around it:

{$IFNDEF Win64}
function TryStr2Float(const _s: string; out _flt: Extended; _DecSeparator: Char = '.'): Boolean; overload;
function TryStr2Float(const _s: string; out _flt: Double; _DecSeparator: Char = '.'): Boolean; overload;
function TryStr2Float(const _s: string; out _flt: Single; _DecSeparator: Char = '.'): Boolean; overload;

This probably also applies to Delphi when compiling for others than the Win32 target, e.g. Win64, Android, IOS etc.

%d bloggers like this: