Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

hp-ux

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

like image 677
Ruairi O'Brien Avatar asked Dec 25 '22 22:12

Ruairi O'Brien


2 Answers

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.

like image 165
Eric Postpischil Avatar answered Jan 27 '23 13:01

Eric Postpischil


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.

like image 22
Gort the Robot Avatar answered Jan 27 '23 11:01

Gort the Robot