Comment 44 for bug 610898

Revision history for this message
Colin Watson (cjwatson) wrote :

This bug has dragged on far too long, and having cleared away some other Wubi bugs I'm finally ready to attack this one. Sorry for taking so long about it.

wubildr.mbr iterates over all partitions (or drives in Windows-speak) and chainloads the first /wubildr (i.e. must be in the root directory) it finds. As such, Wubi is making life difficult for itself by installing wubildr to C: (or, strictly, all drives containing boot.ini). It should really copy it just to the installation target drive; anything else is complexity for the sake of complexity.

So far so good. However, the hard bit is coping with old installations. The substitute grub-mkimage that lupin-support installs is a Unix program, and so works within the Unix filesystem hierarchy; how should it update wubildr on all these partitions that may not even be mounted? Going around and speculatively doing read-write mounts of all the filesystems we can find is generally a recipe for data loss if another operating system was hibernated on the same computer. I'm not certain how big an issue this is, since presumably /host itself would face a similar problem; Linux's NTFS driver has code which at least tries to detect hibernation signatures and refuse to perform a read-write mount, although its FAT driver does not. All the same, I want to minimise the risk from this.

My best candidate so far is to use grub-probe and grub-fstest. These can, respectively and among other things, check the filesystem in use on a partition, and test the existence of a file on a given filesystem, both in a provably read-only fashion. This suggests an algorithm such as the following pseudocode:

  for each partition:
    fs=$(grub-probe $partition)
    if fs in ("fat", "ntfs") and $(grub-fstest $partition ls /wubildr) != "":
      if fs == "fat" and $(grub-fstest $partition ls /hiberfil.sys) != "":
        tmp=$(mktemp)
        grub-fstest $partition cp /hiberfil.sys $tmp
        if size($tmp) < 4096 or first 4096 bytes of $tmp are all zeroes:
          fail("$partition contains Windows hibernation signature")
      tmpdir=$(mktemp -d)
      mount $partition $tmpdir
      update $tmpdir/wubildr
      umount $tmpdir

I've left out lots of details, of course, but I think this is a workable outline. In lucid and maverick, we'll need to enable building grub-fstest and ship it in grub-common, since it's currently missing there (natty has it, though); this would be convenient for GRUB upstream in any case when working with users to diagnose problems. '/usr/share/lupin-support/grub-mkimage --test' could be kept reasonably fast on non-Wubi systems by checking for /host/ubuntu/winboot/ before running lots of grub-probe and grub-fstest commands.

This is going to be a slow and complex operation, and it would be nice to avoid having to do this forever. We could have Wubi drop its build number into /host/ubuntu/winboot/, and then check that to see whether we need to look anywhere other than /host/wubildr.

A variant of this, perhaps simpler, would be to remove any wubildr binaries found by the above process that aren't on a filesystem containing /ubuntu/winboot/wubildr.cfg or similar, and generate /host/wubildr regardless of whether it exists. That way we aren't tied to updating all these different wubildr binaries forever, and we can leave a note somewhere to indicate that we've done it. I think I prefer this approach, although the error handling is delicate.

I now have a suitable test system, so, assuming nothing unforeseen shows up to distract me, I intend to begin implementing this tomorrow.