c: unsigned long long being assigned wrong value on HP-UX Only

c, hp-ux

Solution

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.

Problem

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 :(

Original source