Detecting a hibernated Windows from within Linux

If you have a dual-boot PC with a FAT32 filesystem, quite likely you mount (some of) the same partitions that Windows uses from Linux, so you can access your data from both operating systems.

In some system configurations, when you suspend Windows, it uses its own suspend-to-disk system, saving the system state to a file called hiberfil.sys on C: drive. Next time you power up, Lilo or Grub starts up before Windows, allowing you to start Linux while Windows is still hibernating. You can then shutdown Linux and, at some point, resume Windows.

Problem is, if you mount the FAT parititons from Linux while Windows is hibernated, very bad things may happen. Linux will modify the filesystem without Windows realising. When Windows resumes, it will make false assumptions about the state of the disk which could lead to serious file corruption. I've had this happen to me once.

It would be nice, therefore, if Linux could be configured to refuse to mount the FAT paritions read-write (or at least give a warning) if Windows is hibernating. The problem, then, is how to detect this.

Clean Shutdown bits

My first attempt to implement this was going to use the Clean Shutdown bit which recent versions of windows store in the FAT. This is a flag which Windows sets when it shuts down cleanly (and presumably unsets when it boots up). It's the flag that tells Windows whether it needs to run scandisk on startup. See here. I got as far as writing a program which (I believe, although it's hard to be sure without deliberatly crashing Windows, which I'm reluctant to try) prints out the value of this flag.

Unfortunately, it turned out that Clean Shutdown flag gets set when you hibernate cleanly, too. So no good for detecting a hibernating system. [Update many years later: reading this again, I wonder if the Clean Shutdown bit only gets set if Windows does manage to unmount the partition before hibernating. That would be nice. Not tested.]

hiberfil.sys

The next thing I turned to was hiberfil.sys itself. I couldn't find any documentation for its format on the web, but compared the start of an 'active' hiberfil.sys and inactive hiberfil.sys. The start of the files differ noticably. In particular, the first 4kb of the inactive file was zeros, whereas the active one (containing a hibernating Windows) started with the 4 characters (bytes) "hibr" and then about 158 or so bytes of binary data (then zeros padding out the first 4kbytes as before).

I'm hoping the presence of "hibr" at the start of hiberfil.sys is a good enough indication that a hibernated Windows exists. This is not at all well tested yet!

This bash script (here it is as a .txt file) checks whether the hiberfil is active. This could be incorporated into a script which mounts the dos partitions, e.g.

#!/bin/bash
mountpoint=/mnt/c
if ( checkwin ); then
  mount $mountpoint # assumes this is in fstab
else
  echo "Refusing to mount $mountpoint since there appears to be a hibernated Windows partition"
fi

If you like to use the 'user' option in fstab to allow non-root users to mount the FAT partitions, then a neat trick is to create a second fstab entry, with different mount point and using the ro option. Use this alternative mount point in the checkwin shell script, and it will be able to do its readonly mounting and unmounting without needing root priviledges.

How about getting Windows to unmount some partitions before hibernating?

Might be possible using mountvol... see discussion under "Can I switch from Windows to Linux using Suspend2?" here, and useful info here.


Seb Wills, Feb 2005