[Toybox] [CLEANUP] More thoughts on stat.c cleanup.
Felix Janda
felix.janda at posteo.de
Fri May 31 14:37:16 PDT 2013
On 2013-05-30 at 10:22, Rob Landley wrote:
> Sigh, my idea from the other night didn't pan out. I was hoping that I
> could always pass a long to xprintf(), and then just store the xprintf
> format string and a pointer to the value, dereference it as a long *,
> and let xprintf figure out how much of the stack to consume. (The
> endianness should work out either way, and padding isn't an issue when
> you only have one value.)
>
> The problem is alignment: arm64 can't read a long from an int-aligned
> address. 8 byte types need 8 byte alignment, not 4. Blah.
>
> What I really want is some variant of vprintf() that can start reading
> values from a pointer location instead of a va_list. Unfortunately,
> libc hasn't got one. Nor has it got "I passed you a pointer,
> dereference it" notation from the actual printf logic that knows the
> size of the data type...
Hmm, I should have mentioned that I also had an idea along that line and
would also be happy if there was such a variant of vprintf(). On some
systems va_list should actually be implemented in that way.
> Ok, I need to collate the "long" and "long long" types into two printf
> groups. And isolate the stuff with extra processing....
>
> Hang on, this is wrong:
>
> case 'X':
> xprintf("%llu", stat->st_atime);
>
> That's just "long", not "long long". (In the kernel source, see
> arch/include/uapi/asm/stat.h, definition of struct stat _and_ struct
> stat64, it's unsigned long in both. I have no idea why st_mtime_nsec is
> "int", but int and long are equivalent on 32 bit x86 so it's just weird
> and not actually incorrect.)
I didn't really check the format strings for correctness. It seemed like
it would get a headache to get them right on all architectures.
> And that's the problem: on a 32 bit system, long is the same size as
> int, not as uint64_t. How on earth does that work? (Is gcc promoting
> the type...?)
>
> $ CFLAGS="--static -Wall"
> CROSS_COMPILE=~/cross-compiler-i686/bin/i686- make
> $ stat -c %Y /
> 1368946682
> $ ./toybox stat -c %Y /
> 104448161786
>
> So that's a no, then. It's just buggy.
>
> Ok, how portable is that type?
>
> $ grep "st_mtime;" arch/*/include/uapi/asm/stat.h \
> | sed 's/^.*://;s/[ \t][ \t]*/ /g' | sort -u
> int st_mtime; /* Time of last modification. */
> signed int st_mtime;
> time_t st_mtime;
> unsigned int st_mtime;
> unsigned long st_mtime;
> unsigned long st_mtime; /* Time of last modification. */
>
> Apparently not. What size is time_t anyway? It's __kernel_time_t. Which
> is...
>
> $ find $(find . -name uapi) -name "*.h" | xargs grep __kernel_time_t
> | grep typedef
> ./include/uapi/asm-generic/posix_types.h:typedef __kernel_long_t
> __kernel_time_t;
> $ find $(find . -name uapi) -name "*.h" | xargs grep __kernel_long_t
> | grep typedef
> ./arch/x86/include/uapi/asm/posix_types_x32.h:typedef long long
> __kernel_long_t;
> ./include/uapi/asm-generic/posix_types.h:typedef long
> __kernel_long_t;
>
> They special cased 32 bit x86 and nobody else did. Bravo. So 32 bit arm
> still has a 2038 problem? (What?)
>
> Right. Looks like I have to hit it with a typecast, _and_ I might have
> to check the other types to see if they match up with what printf
> expects...
>
> Lemme get back to this one. :)
It sounds like great fun.
Felix
More information about the Toybox
mailing list