[Toybox] [df] percentage different from GNU df

Roy Tam roytam at gmail.com
Thu Nov 8 22:24:39 PST 2012


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);
 }

 void df_main(void)
 {



>
>> Thanks for the heads up,
>>
>> Rob



More information about the Toybox mailing list