Subject: bug#10363: df vs. long-named /dev/disk/by-uuid/... file system device names

From: Jim Meyering <[email-masked]>
Date: Mon, 02 Jan 2012 18:34:20 +0100

Jim Meyering wrote:
...
> +  char *dev_name = xstrdup (disk);
> +  char *resolved_dev;
> +
> +  /* On some systems, dev_name is a long-named symlink like
> +     /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 pointing
> +     to a much shorter and more useful name like /dev/sda1.
> +     When process_all is true and dev_name is a symlink whose name starts
> +     with /dev/disk/by-uuid/ use the resolved name instead.  */
> +  if (process_all
> +      && STRPREFIX (dev_name, "/dev/disk/by-uuid/")
> +      && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))
> +    {
> +      free (dev_name);
> +      dev_name = resolved_dev;
> +    }

I noticed that there is a similar problem on any recent
system with an encrypted root partition.
In that case, the kernel is booted with an argument like this

    root=/dev/mapper/luks-88888888-8888-8888-8888-888888888888

and that same name appears in /proc/mounts and thus, even with
the proposed patch, in df's "Filesystem" column.  The knee-jerk
reaction is to do this:

     if (process_all
         && (STRPREFIX (dev_name, "/dev/disk/by-uuid/")
             || STRPREFIX (dev_name, "/dev/mapper/luks-"))
         && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))

but will the prefix always be spelled that way?

Now, I'm thinking about making this a little more future-proof by
matching the UUID part /[0-9a-fA-F-]{36}$/ instead.
I.e., testing something like this:

     if (process_all
         && has_uuid_suffix (dev_name)
         && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))

using this new function:

  static bool
  has_uuid_suffix (char const *s)
  {
    size_t len = strlen (s);
    return (36 < len
            && strspn (s + len - 36, "-0123456789abcdefABCDEF") == 36);
  }