[Toybox] Stat %Z - What are valid values?
Rob Landley
rob at landley.net
Wed Feb 8 13:05:13 PST 2017
I still have this todo item:
On 12/30/2016 11:28 AM, darken wrote:
> I've seen a value of "18446744072363093454" for stat %Z (seconds since
> epoch), for some files on a users device (Android 6.01).
To which Elliot replied with:
On 12/30/2016 01:39 PM, enh wrote:
> time_t on 32-bit Android is 32 bits.
>
> that particular value looks like a sign-extension of 0xAFBEADCE, which
> is still some time in 2063. (so i'd assume this device's clock is set
> wrong, and i'd assume -- since this is presumably a 32-bit device with
> a signed 32-bit time_t -- that that's going to be causing other
> problems too.)
Then I said:
> Or if it's signed, that's -1346458162 which would be... sometime in the
> 1930's? hmmm... "./date -D %s -d -1346458162" is failing under glibc,
> and failing _differently_ under musl. (Wheee.)
At which point I got distracted going off on a tangent instead of just
using "touch -d".
Years ago Linus ruled ex cathedra that time_t is gonna stay signed on
Linux (because otherwise you can't represent times before Jan 1 1970,
which a lot of people's birthdays still are):
https://lkml.org/lkml/2011/8/31/246
Which means a 32 bit time_t has the year 2038 problem (and x32 needs a
64 bit time_t to stay relevant).
The problem here _isn't_ about casting time_t to unsigned, because it
isn't an unsigned value. (And unsigned 64 bit value still couldn't
represent times before 1970: it has to _remain_ signed after being
promoted to 64 bits or it's broken.)
That's why I didn't apply Elliott's patch with the sizeof() and typecast
staircase: I don't see how it can be the proper fix to the reported problem:
> with 64-bit toybox:
>
> angler:/ # date 060200002064
That date is past 2038...
> Mon Jun 2 00:00:00 GMT 2064
> angler:/ # rm /data/local/tmp/empty
> angler:/ # touch /data/local/tmp/empty
> angler:/ # ls -l /data/local/tmp/empty
> -rw-rw-rw- 1 root root 0 2064-06-02 00:00 /data/local/tmp/empty
> angler:/ # stat /data/local/tmp/empty
> File: `/data/local/tmp/empty'
> Size: 0 Blocks: 0 IO Blocks: 512 regular empty file
> Device: fd00h/64768d Inode: 3014659 Links: 1
> Access: (666/-rw-rw-rw-) Uid: ( 0/ root) Gid: ( 0/ root)
> Access: 2064-06-02 00:00:11.746667836
> Modify: 2064-06-02 00:00:11.746667836
> Change: 2064-06-02 00:00:11.746667836
> angler:/ # stat -c "%z %Z" /data/local/tmp/empty
> 2064-06-02 00:00:11.746667836 2979590411
> angler:/ # ^D
A 64 bit platform can represent that but a 32 bit one can't, because
it's past y2038.
> then with 32-bit toybox:
>
> angler:/ # ls -l /data/local/tmp/empty
> -rw-rw-rw- 1 root root 0 1928-04-26 17:31 /data/local/tmp/empty
Because time_t is a 32 bit signed value there, so that bit pattern
represents a negative number.
> angler:/ # stat /data/local/tmp/empty
> File: `/data/local/tmp/empty'
> Size: 0 Blocks: 0 IO Blocks: 512 regular empty file
> Device: fd00h/64768d Inode: 3014659 Links: 1
> Access: (666/-rw-rw-rw-) Uid: ( 0/ root) Gid: ( 0/ root)
> Access: 1928-04-26 17:31:55.746667836
> Modify: 1928-04-26 17:31:55.746667836
> Change: 1928-04-26 17:31:55.746667836
> angler:/ # stat -c "%z %Z" /data/local/tmp/empty
> 1928-04-26 17:31:55.746667836 18446744072394174731
Why is "stat" showing the same data as "ls" a bad thing here? Your patch
to stat makes it diverge from ls? On a local i686-musl build:
/ # touch -d 1928-04-26T00:00:00 walrus
/ # ls -l walrus
-rw-r--r-- 1 root root 0 1928-04-26 00:00 walrus
/ # stat walrus
File: `walrus'
Size: 0 Blocks: 0 IO Blocks: 512 regular empty file
Device: 801h/2049d Inode: 14574425 Links: 1
Access: (644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 1928-04-26 00:00:00.000000000
Modify: 1928-04-26 00:00:00.000000000
Change: 2017-02-08 20:58:37.009291677
/ #
> two patches attached. one avoids sign extension for all calls to
> `out`, fixing %Z for systems with a signed 32-bit time_t.
What does this patch fix?
Rob
More information about the Toybox
mailing list