[Toybox] [df] percentage different from GNU df

Rob Landley rob at landley.net
Fri Nov 9 08:22:18 PST 2012


On 11/09/2012 12:24:39 AM, Roy Tam wrote:
> Hello,
> 
> 2012/11/9 Roy Tam <roytam at gmail.com>:
> > Hello,
> >
> > 2012/11/9 Rob Landley <rob at landley.net>:
> >> On 10/28/2012 10:50:50 PM, Roy Tam wrote:
> >>>
> >>> Hello,
> >>>
> >>> I noticed that toybox df shows different percentage from GNU df.
> >>> GNU df calculates percentage by used/(used+free) while toybox use
> >>> (blocks-free)/blocks.
> >>> (which one is better by the way?)
> >>
> >>
> >> According to posix-2008:
> >>
> >>> <percentage used>
> >>>
> >>> The percentage of the normally available space that is currently  
> allocated
> >>> to all
> >>> files on the file system. This shall be calculated using the  
> fraction:
> >>>   <space used>/( <space used>+ <space free>)
> >>> expressed as a percentage. This percentage may be greater than  
> 100 if
> >>> <space free> is
> >>> less than zero. The percentage value shall be expressed as a  
> positive
> >>> integer, with
> >>> any fractional result causing it to be rounded to the next highest
> >>> integer.
> >>
> >>
> >> The "space used" and "space free" entries are the used/available  
> displayed
> >> in columns 3 and 4. The "any fractional result" implies that you do
> >> something like:
> >>
> >>   pct=(used*100)/(used+free)
> >>   if (pct*(used+free) != (used*100)) pct++;
> >>
> >> (Except all with 64 bit math so overflow sucks less.)
> >>
> >>
> >>> toybox$ ../busybox/busybox df
> >>> Filesystem           1K-blocks      Used Available Use% Mounted on
> >>> udev                     10240         0     10240   0% /dev
> >>> tmpfs                    12456       160     12296   1% /run
> >>> /dev/disk/by-uuid/4277274d-e9a1-42ff-a247-b75bde522deb
> >>>                        1913244   1151656    664400  63% /
> >>> tmpfs                    24912         0     24912   0% /run/shm
> >>
> >>
> >> 160/(160+12296.0)
> >> 0.012845215157353885
> >>
> >> Not doing the pedantic rounding up.
> >>
> >>
> >>> toybox$ df
> >>> Filesystem           1K-blocks      Used Available Use% Mounted on
> >>> rootfs                 1913244   1151656    664400  64% /
> >>> udev                     10240         0     10240   0% /dev
> >>> tmpfs                    12456       160     12296   2% /run
> >>> /dev/disk/by-uuid/4277274d-e9a1-42ff-a247-b75bde522deb
> >>>                        1913244   1151656    664400  64% /
> >>> tmpfs                    24912         0     24912   0% /run/shm
> >>
> >>
> >> Doing the pedantic rounding up.
> >>
> >>
> >>> toybox$ ./toybox df
> >>> Filesystem      1K-blocks       Used Available Use% Mounted on
> >>> tmpfs               24912          0     24912   0% /run/shm
> >>> /dev/sda1         1913244    1151656    664400  66% /
> >>> tmpfs               12456        160     12296   2% /run
> >>> udev                10240          0     10240   0% /dev
> >>
> >>
> >> Showing used as a percentage of 1K-blocks, ignoring "available"  
> altogether.
> >>
> >> Right, I fixed it to match what the standard requires, which seems  
> to be
> >> what upstream is doing.
> >>
> >
> > I'm now hitting segfault with hg head.
> >
> > toybox$ CFLAGS="-O0 -g" make
> > scripts/make.sh
> > Make generated/config.h from .config.
> > Extract configuration information from toys/*.c files...
> > Generate headers from toys/*/*.c...
> > generated/newtoys.h
> > generated/globals.h
> > generated/help.h
> > Extract help text from Config.in.
> > Library probe...
> > Compile toybox...
> > toybox$ gdb --args ./toybox_unstripped df
> > GNU gdb (GDB) 7.4.1-debian
> > Copyright (C) 2012 Free Software Foundation, Inc.
> > License GPLv3+: GNU GPL version 3 or later  
> <http://gnu.org/licenses/gpl.html>
> > This is free software: you are free to change and redistribute it.
> > There is NO WARRANTY, to the extent permitted by law.  Type "show  
> copying"
> > and "show warranty" for details.
> > This GDB was configured as "i486-linux-gnu".
> > For bug reporting instructions, please see:
> > <http://www.gnu.org/software/gdb/bugs/>...
> > Reading symbols from /home/roy/toybox/toybox_unstripped...done.
> > (gdb) r
> > Starting program: /home/roy/toybox/toybox_unstripped df
> > Filesystem      1K-blocks       Used Available Use% Mounted on
> >
> > Program received signal SIGSEGV, Segmentation fault.
> > 0xb7e867a4 in vfprintf () from  
> /lib/i386-linux-gnu/i686/cmov/libc.so.6
> > (gdb) bt
> > #0  0xb7e867a4 in vfprintf () from  
> /lib/i386-linux-gnu/i686/cmov/libc.so.6
> > #1  0xb7e87270 in vprintf () from  
> /lib/i386-linux-gnu/i686/cmov/libc.so.6
> > #2  0x0804ce44 in xprintf (format=0x805c445 "%s% *ld % 10ld % 9ld %
> > 3ld%% %s\n") at lib/lib.c:152
> > #3  0x08051c78 in show_mt (mt=0x806b8b0) at toys/posix/df.c:94
> > #4  show_mt (mt=0x806b8b0) at toys/posix/df.c:49
> > #5  0x08051db6 in df_main () at toys/posix/df.c:159
> > #6  0x0804b3b2 in toy_exec (argv=0xbffffd78) at main.c:104
> > #7  0x0804b3ed in toybox_main () at main.c:118
> > #8  0x0804b3b2 in toy_exec (argv=0xbffffd74) at main.c:104
> > #9  0x0804b3ed in toybox_main () at main.c:118
> > #10 0x0804b14a in main (argc=2, argv=0xbffffd74) at main.c:159
> > (gdb) frame 2
> > #2  0x0804ce44 in xprintf (format=0x805c445 "%s% *ld % 10ld % 9ld %
> > 3ld%% %s\n") at lib/lib.c:152
> > 152             vprintf(format, va);
> > (gdb) print *va
> > $1 = 139 '\213'
> > (gdb) list
> > 147     void xprintf(char *format, ...)
> > 148     {
> > 149             va_list va;
> > 150             va_start(va, format);
> > 151
> > 152             vprintf(format, va);
> > 153             if (ferror(stdout)) perror_exit("write");
> > 154     }
> > 155
> > 156     void xputs(char *s)
> > (gdb) print va
> > $2 = (va_list) 0xbffffae4 "\213\271\006\b\024"
> > (gdb)
> >
> 
> Alright, a quick fix is done:
> --- df.c        2012-11-09 05:03:03.000000000 +0800
> +++ df.c_qf     2012-11-09 14:23:15.000000000 +0800
> @@ -83,20 +83,20 @@
> 
>         device = *mt->device == '/' ? realpath(mt->device, NULL) :  
> NULL;
>         if (!device) device = mt->device;
> 
>         // Figure out appropriate spacing
>         len = 25 - strlen(device);
>         if (len < 1) len = 1;
>         if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) {
> -               xprintf("%s %ld %ld %ld %ld%% %s\n", device, size,  
> used, avail,
> +               xprintf("%s %lld %lld %lld %lld%% %s\n", device, size,
> used, avail,
>                                 percent, mt->dir);
>         } else {
> -               xprintf("%s% *ld % 10ld % 9ld % 3ld%% %s\n", device,  
> len,
> +               xprintf("%s% *lld % 10lld % 9lld % 3lld%% %s\n",  
> device, len,
>                         size, used, avail, percent, mt->dir);
>         }
> 
>         if (device != mt->device) free(device);
>  }

Oops.

(Worked fine when I built it on my 64 bit netbook. :)

Applied, thanks.

Rob
 1352478138.0


More information about the Toybox mailing list