Thursday, 30 July 2009

Multi-boot is dead easy. Yeah right.

My comp's motherboard flipped (some capacitors blew making it hard to boot the machine) so I got this crazy idea of buying a new harddrive and use one of the existing ones removing the oldest disks (one 120GB, one 160GB) and creating a multi-boot machine with XP and Ubuntu.

Theory is that you install XP, then install Ubuntu and everything works. This is what happened to me.

I installed XP, all the service packs and most of the software I needed (iTunes, FireFox, Thunderbird, Spotify, DVD Profiler etc). Then I installed Ubuntu so that the XP disk was the bootable disk, so Grub was installed there. End result was that neither XP nor Ubuntu booted. After some mucking about I got Ubuntu to start but XP was completely dead. It was in fact so dead that even when I tried reinstall, it didn't work until I booted the rescue disk and did "fixmbr".

I'm not going to go through all I had to do to get things to work, needless to say I ended up installing XP about four times from scratch and Ubuntu twice. Once because gparted somehow messed up the XP disk after I tried to resize the C-drive to 1TB. I had done it the first time using the Ubuntu Live CD so I thought it would work again. It didn't. Part of the trouble was my XP installation disk is original so it doesn't support disk sizes greater than 130GB (SP2 added that support).

The way I managed this in the end was this:
  • Remove the 1TB disk from the machine.
  • Install Ubuntu on the 500GB disk, Grub and all.
  • Attach the 1TB disk to the machine and remove the 500GB disk.
  • Install XP and updated it. Create the second partition on the leftover disk space.
  • Attach the 500GB disk and make sure the system boots using this disk.
  • Edit grub's menu.lst (in /boot/grub) and add the XP there and map the drives so that XP imagines it's on the first HD. This is done by adding the following section:
title Windows 95/98/NT/2000
root (hd0,0)
map (hd0) (hd1)
map (hd1) (hd0)
chainloader +1
and then run "sudo update-grub".

To me it looked like trying to install Grub on XP's disk while Ubuntu was on a different drive was the problem. I ended up messing XP's MBR several times attempting this. The last part on my list is required because XP likes to think it's the top dog in a system (i.e. on the first drive).

So now I have a dual-boot, although XP has two partitions instead of one. But I decided this was the last time I'm installing XP on my home machine. If I still require a Microsoft product the next time I'm up for a system upgrade it will probably be Windows 7.

Thursday, 2 July 2009

How Not To Use Goto In C Init Functions

There is the idea that Goto is useful in some complex init functions to make the code simpler. Such as:

if (OK != doSomething()) goto cleanup;
if (OK != doSomethingElse()) goto cleanup;

There could dozens of functions that need to be called except if something goes wrong in which case the rest of the init functions should not be called.

This is thought to be better because the normal style of if's makes the code much more complex. But there is a better way of doing initialization code like this that doesn't make the code any longer:

error = (!error) && doSomething();
error = (!error) && doSomethingElse();

Or, if you want to know which function failed you can either have different return codes for each function or do this:

error = (!error) && (doSomething() << SHIFT_DOSOMETHING);
error = (!error) && (doSomething Else() << SHIFT_DOSOMETHINGELSE);

I would prefer each function returning it's own error code because the latter style is not quite as easy to read and relies on functions returning 1 on error (the first version works with any return values).

This is a pretty easy way of solving the same problem and does not add any cyclomatic complexity and keeps the code short, without any extra constructs.