Had a bit of trouble coming up with a title for this question.
I recently fumbled in to the world of C.
I have a little bit of code that basically shows the capacity and free space of a drive. It works fine on a few different Linux distros I've tried as well as Solaris and AIX. I recently compiled on a HP-UX PA-RISC box and got (in my opinion) a really strange error.
struct statfs fsStat;
err = statfs(rootPath,&fsStat);
unsigned long long totalBytes = (unsigned long long)(fsStat.f_bsize * fsStat.f_blocks);
In GDB when I do:
p (fsStat.f_bsize * fsStat.f_blocks)
The result is 1335205888 But after the calculation is run, when I do
p totalByes
The result is 18446744071562067968
Any information that might even give me an idea of what to try here would be really great. Used to think I knew how to program until I started doing multi platform C :(
Hypothesis:
The multiplication overflowed, so fsStat.f_bsize * fsStat.f_blocks
produced an overflow result of -2147483648. When this was converted to unsigned long long
, it produced 18446744071562067968, which is 0xffffffff80000000, the result of wrapping -2147483648 in a 64-bit unsigned format. GDB uses different arithmetic than C, so it displayed the mathematically correct result.
To fix this, change (unsigned long long) (fsStat.f_bsize * fsStat.f_blocks)
to (unsigned long long) fsStat.f_bsize * fsStat.f_blocks
, to convert to the wider integer format before multiplication.
Better than unsigned long long
would be to use either uint64_t
(from <stdint.h>
) or a type supplied by the platform (some Linux header) for working with disk sizes.
My guess is that f_bsize
and f_blocks
are of type int
. The value is probably overflowing into a negative value.
Try casting each of these values to unsigned long long
before multiplying them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With