Subject: bug#6816: df bug on 64-bit Solaris (need to use getextmntent)

From: Eric Blake <[email-masked]>
Date: Wed, 15 Sep 2010 16:18:37 -0600

[digging through older mail, and sorry for the delayed reply]

On 08/06/2010 01:56 PM, Wood, David wrote:
> Hello,
>
>> From mnttab(4) on Solaris 10:
>
>       Applications requiring device number information for mounted
>       file  systems  should  use  the  getextmntent(3C) interface,
>       which functions properly in either 32-  or  64-bit  environ-
>       ments.
>
> Indeed, if one compiles coreutils 64-bit, the logic breaks down around line 718 of df.c:
>
>          if (statp->st_dev == me->me_dev
>              &&  !STREQ (me->me_type, "lofs")
>              &&  (!best_match || best_match->me_dummy || !me->me_dummy))
>            {
>
> At this point, me->me_dev contains a wrongly packed (32-bit) device number, which forces the find_mount_point() code path (causing other unpleasantries).  The following patch against coreutils v8.5 fixes the problem:

Thanks for the report.  Yes, this needs to be folded into gnulib, but it 
also needs an m4 check for getextmntent, and it would be nice to get by 
with less in-function #ifdefs.

>
> --- mountlist.c 3 Aug 2010 21:53:14 -0000       1.1.1.4
> +++ mountlist.c 6 Aug 2010 18:16:55 -0000       1.2
> @@ -107,6 +107,10 @@
>   # include<sys/mnttab.h>
>   #endif
>
> +#ifdef MOUNTED_GETEXTMNTENT     /* need makedev when using getextmntent */
> +# include<sys/mkdev.h>
> +#endif
> +
>   #ifdef MOUNTED_VMOUNT           /* AIX.  */
>   # include<fshelp.h>
>   # include<sys/vfs.h>
> @@ -125,7 +129,8 @@
>
>   #undef MNT_IGNORE
>   #if defined MNTOPT_IGNORE&&  defined HAVE_HASMNTOPT
> -# define MNT_IGNORE(M) hasmntopt (M, MNTOPT_IGNORE)
> +/* cast to a mnttab struct pointer to also support extmnttab */
> +# define MNT_IGNORE(M) hasmntopt ((struct mnttab *) M, MNTOPT_IGNORE)
>   #else
>   # define MNT_IGNORE(M) 0
>   #endif
> @@ -714,7 +719,11 @@
>
>   #ifdef MOUNTED_GETMNTENT2       /* SVR4.  */
>     {
> +# ifdef MOUNTED_GETEXTMNTENT
> +    struct extmnttab mnt;
> +# else
>       struct mnttab mnt;
> +# endif
>       char *table = MNTTAB;
>       FILE *fp;
>       int ret;
> @@ -755,7 +764,11 @@
>         ret = errno;
>       else
>         {
> +# ifdef MOUNTED_GETEXTMNTENT
> +        while ((ret = getextmntent (fp,&mnt, sizeof (struct extmnttab))) == 0)
> +# else
>           while ((ret = getmntent (fp,&mnt)) == 0)
> +# endif
>             {
>               me = xmalloc (sizeof *me);
>               me->me_devname = xstrdup (mnt.mnt_special);
> @@ -764,7 +777,11 @@
>               me->me_type_malloced = 1;
>               me->me_dummy = MNT_IGNORE (&mnt) != 0;
>               me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
> +# ifdef MOUNTED_GETEXTMNTENT
> +            me->me_dev = makedev(mnt.mnt_major, mnt.mnt_minor);
> +# else
>               me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);
> +# endif
>
>               /* Add to the linked list. */
>               *mtail = me;
>
>
>
>

-- 
Eric Blake   [email-masked]    +1-801-349-2682
Libvirt virtualization library http://libvirt.org