Re: [Toybox] Stat %Z - What are valid values?
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 06022064 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: 0Blocks: 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.0 Modify: 1928-04-26 00:00:00.0 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 ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
On 01/25/2017 06:25 PM, Rich Felker wrote: >> According to man 2 time: >> >> time() returns the time as the number of seconds since the Epoch, >> 1970-01-01 00:00:00 + (UTC). >> >> I.E. the definition of unix time is UTC. So %s _not_ being UTC is silly. > > Nobody is questioning whether the input read by %s is UTC. The > question is whether the output struct tm is UTC or local. > >> My use case (and presumably most people's) is turning a time string into >> a struct timespec. What the actual struct tm fields are is irrelevant to >> that as long as mktime() translates the result back to the right number. > > mktime interprets it as local, in which case strptime would have to be > doing the inverse operation, converting from UTC to local for the > struct tm output. > > On the other hand strptime output may also be used with timegm (or a > hand-rolled version thereof). If mktime is in posix and timegm isn't, that probably means something. People can write hand-rolled code to do anything, doesn't make it right. > This is what you would do if you were > parsing a sting in UTC. With all the existing/standard fields, > strptime is completely agnostic with regards to what you want to do > with the output. Only with %s will it need a hard-coded assumption > about what you're going to do with the output. Not if it's symmetrical. If I don't _change_ the time zone between populating the struct tm and consuming the struct tm, I should get the same result back out, which is what I'm trying to accomplish. >From man timegm: For a portable version of timegm(), set the TZ environment variable to UTC, call mktime(3) and restore the value of TZ. I.E. the "portable" behavior is symmetrical if you don't change the timezone in the middle. If you do, that's obvious pilot error. And if I want everything to happen in UTC, I can set TZ (which the date command does for -u already). >> The struct tm has a timezone field in it. As long as strptime sets the >> timezone when it adjusts the hours so mktime() can adjust it _back_, the >> result is the same number you fed into %s. Which is the point of the >> exercise. > > mktime cannot use the timezone field of struct tm. It's required to > assume the struct tm is in local time in the current timezone. As long as it's symmetrical, it works for me. If posix requires mktime to use the current timezone and that's the _only_ way it provides of turning struct tm into time_t, then it implicitly requires strptime to mirror that when turning an ascii representation of time_t into a struct tm. It needs to do the opposite of what mktime does, so mktime can undo it. > Rich Rob ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
On Wed, Jan 25, 2017 at 05:15:37PM -0600, Rob Landley wrote: > On 01/24/2017 06:10 PM, Rich Felker wrote: > >>> strptime with %s? I suspect there are some nasty underspecified issues > >>> with how it interacts with timezones. > >> > >> I thought unix time was always UTS and the timezone just affected how it > >> was displayed? > > > > The problem is that strptime produces a struct tm. When the fields > > it's parsing to produce this struct tm are "broken down time" fields, > > strptime does not need to know/care whether the caller is going to > > interpret the struct tm as UTC or local time; it's just a bunch of > > numbers. But when strptime is going to take a unix time value (seconds > > since epoch) and convert it to struct tm, it matters whether the > > caller is supposed to treat that struct tm as UTC or local. > > According to man 2 time: > > time() returns the time as the number of seconds since the Epoch, > 1970-01-01 00:00:00 + (UTC). > > I.E. the definition of unix time is UTC. So %s _not_ being UTC is silly. Nobody is questioning whether the input read by %s is UTC. The question is whether the output struct tm is UTC or local. > My use case (and presumably most people's) is turning a time string into > a struct timespec. What the actual struct tm fields are is irrelevant to > that as long as mktime() translates the result back to the right number. mktime interprets it as local, in which case strptime would have to be doing the inverse operation, converting from UTC to local for the struct tm output. On the other hand strptime output may also be used with timegm (or a hand-rolled version thereof). This is what you would do if you were parsing a sting in UTC. With all the existing/standard fields, strptime is completely agnostic with regards to what you want to do with the output. Only with %s will it need a hard-coded assumption about what you're going to do with the output. > The struct tm has a timezone field in it. As long as strptime sets the > timezone when it adjusts the hours so mktime() can adjust it _back_, the > result is the same number you fed into %s. Which is the point of the > exercise. mktime cannot use the timezone field of struct tm. It's required to assume the struct tm is in local time in the current timezone. Rich ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
On 01/24/2017 06:10 PM, Rich Felker wrote: >>> strptime with %s? I suspect there are some nasty underspecified issues >>> with how it interacts with timezones. >> >> I thought unix time was always UTS and the timezone just affected how it >> was displayed? > > The problem is that strptime produces a struct tm. When the fields > it's parsing to produce this struct tm are "broken down time" fields, > strptime does not need to know/care whether the caller is going to > interpret the struct tm as UTC or local time; it's just a bunch of > numbers. But when strptime is going to take a unix time value (seconds > since epoch) and convert it to struct tm, it matters whether the > caller is supposed to treat that struct tm as UTC or local. According to man 2 time: time() returns the time as the number of seconds since the Epoch, 1970-01-01 00:00:00 + (UTC). I.E. the definition of unix time is UTC. So %s _not_ being UTC is silly. My use case (and presumably most people's) is turning a time string into a struct timespec. What the actual struct tm fields are is irrelevant to that as long as mktime() translates the result back to the right number. The struct tm has a timezone field in it. As long as strptime sets the timezone when it adjusts the hours so mktime() can adjust it _back_, the result is the same number you fed into %s. Which is the point of the exercise. (Remember when Linux systems used to have a "store system clock in GMT instead of localtime" option during config, and the config option went away because nobody ever _didn't_ do that? Yeah, that.) > Rich Rob ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
On Tue, Jan 24, 2017 at 05:47:46PM -0600, Rob Landley wrote: > > > On 01/21/2017 06:25 PM, Rich Felker wrote: > > On Sat, Jan 21, 2017 at 03:18:28PM -0600, Rob Landley wrote: > >>> 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.) > >>> > >>> /me goes down tangent rathole debugging why. > >> > >>> > >>> (Answer: musl doesn't implement %s at all, and glibc doesn't allow the > >>> %s value it converts to be negative.) > >> > >> Query: does bionic strptime() handle %s, and if so does it handle > >> negative input values? (If not I suppose I can try to special case this > >> in toybox, but ew.) > >> > >> Also, Rich: any interest in adding this to musl? > > > > strptime with %s? I suspect there are some nasty underspecified issues > > with how it interacts with timezones. > > I thought unix time was always UTS and the timezone just affected how it > was displayed? The problem is that strptime produces a struct tm. When the fields it's parsing to produce this struct tm are "broken down time" fields, strptime does not need to know/care whether the caller is going to interpret the struct tm as UTC or local time; it's just a bunch of numbers. But when strptime is going to take a unix time value (seconds since epoch) and convert it to struct tm, it matters whether the caller is supposed to treat that struct tm as UTC or local. Rich ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
On Tue, Jan 24, 2017 at 3:47 PM, Rob Landleywrote: > > > On 01/21/2017 06:25 PM, Rich Felker wrote: >> On Sat, Jan 21, 2017 at 03:18:28PM -0600, Rob Landley wrote: 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.) /me goes down tangent rathole debugging why. >>> (Answer: musl doesn't implement %s at all, and glibc doesn't allow the %s value it converts to be negative.) >>> >>> Query: does bionic strptime() handle %s, and if so does it handle >>> negative input values? (If not I suppose I can try to special case this >>> in toybox, but ew.) >>> >>> Also, Rich: any interest in adding this to musl? >> >> strptime with %s? I suspect there are some nasty underspecified issues >> with how it interacts with timezones. > > I thought unix time was always UTS and the timezone just affected how it > was displayed? > >> All the standard specifiers work >> with broken-down (struct tm) time so timezone is irrelevant to how >> they operate. > > I'm tempted to add support for it myself, but the problem is the format > could be "time=[%s]" and I'd have to parse context data. (I can just > strstr() but I'd have to make sure it wasn't %%s...) > >> So the answer isn't no, but "it's complicated", and needs more >> research on how other implementations work, > > I think it's just glibc so far? i have an open feature request for %s in bionic (http://code.google.com/p/android/issues/detail?id=229155) and iirc freebsd and netbsd both have it, but different (gmtime versus localtime). openbsd didn't have it. ios matches freebsd. which meant ios and glibc disagree, which is why that's on my big list of things i'm not sure what to do about. glibc was probably there first, but ios is probably more relevant. i'd rather work on making the icu4c APIs available to apps anyway :-) >> if they're consistent, >> pros and cons of different possible behaviors, etc. > > It's not that big a deal for me to do it myself, I just thought I'd > raise the issue. If bionic and musl both add %s that supports negative > numbers, I'm happy to leave glibc as broken until they catch up. If they > don't, it makes sense to do it myself... > >> Rich > > Rob -- Elliott Hughes - http://who/enh - http://jessies.org/~enh/ Android native code/tools questions? Mail me/drop by/add me as a reviewer. ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
On 01/21/2017 06:25 PM, Rich Felker wrote: > On Sat, Jan 21, 2017 at 03:18:28PM -0600, Rob Landley wrote: >>> 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.) >>> >>> /me goes down tangent rathole debugging why. >> >>> >>> (Answer: musl doesn't implement %s at all, and glibc doesn't allow the >>> %s value it converts to be negative.) >> >> Query: does bionic strptime() handle %s, and if so does it handle >> negative input values? (If not I suppose I can try to special case this >> in toybox, but ew.) >> >> Also, Rich: any interest in adding this to musl? > > strptime with %s? I suspect there are some nasty underspecified issues > with how it interacts with timezones. I thought unix time was always UTS and the timezone just affected how it was displayed? > All the standard specifiers work > with broken-down (struct tm) time so timezone is irrelevant to how > they operate. I'm tempted to add support for it myself, but the problem is the format could be "time=[%s]" and I'd have to parse context data. (I can just strstr() but I'd have to make sure it wasn't %%s...) > So the answer isn't no, but "it's complicated", and needs more > research on how other implementations work, I think it's just glibc so far? > if they're consistent, > pros and cons of different possible behaviors, etc. It's not that big a deal for me to do it myself, I just thought I'd raise the issue. If bionic and musl both add %s that supports negative numbers, I'm happy to leave glibc as broken until they catch up. If they don't, it makes sense to do it myself... > Rich Rob ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
On Sat, Jan 21, 2017 at 03:18:28PM -0600, Rob Landley wrote: > > 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.) > > > > /me goes down tangent rathole debugging why. > > > > > (Answer: musl doesn't implement %s at all, and glibc doesn't allow the > > %s value it converts to be negative.) > > Query: does bionic strptime() handle %s, and if so does it handle > negative input values? (If not I suppose I can try to special case this > in toybox, but ew.) > > Also, Rich: any interest in adding this to musl? strptime with %s? I suspect there are some nasty underspecified issues with how it interacts with timezones. All the standard specifiers work with broken-down (struct tm) time so timezone is irrelevant to how they operate. So the answer isn't no, but "it's complicated", and needs more research on how other implementations work, if they're consistent, pros and cons of different possible behaviors, etc. Rich ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
On 12/30/2016 04:01 PM, enh wrote: > On Fri, Dec 30, 2016 at 1:51 PM, Rob Landleywrote: >> On 12/30/2016 01:39 PM, enh wrote: >>> 1928-04-26 17:31:55.746667836 18446744072394174731 >> >> Really we can partially blame posix here for not specifying whether >> time_t is signed or unsigned. (If it's unsigned it can't represent times >> before January 1, 1970, as the code on the left is doing. And there >> _are_ times before then. So I think we have to treat it as signed and go >> "32 bit timestamps gotta go away before 2038".) > > if you want to be amused/horrified, you should look at the tzcode > stuff. iirc they only recently agreed that time_t is an integral type. Note to self: it's easier to review patches after a while if you include the test case of the thing it fixes in the patch. Right, this thread... > 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.) > > /me goes down tangent rathole debugging why. ... > > (Answer: musl doesn't implement %s at all, and glibc doesn't allow the > %s value it converts to be negative.) Query: does bionic strptime() handle %s, and if so does it handle negative input values? (If not I suppose I can try to special case this in toybox, but ew.) Also, Rich: any interest in adding this to musl? > with 64-bit toybox: > > angler:/ # date 06022064 > Mon Jun 2 00:00:00 GMT 2064 Under Ubuntu 14.04 with 64-bit glibc, that becomes $ ./date 06022064 date: bad date '06022064'; Fri Jun 2 00:00:00 CST 2064 != Mon Jun 2 01:00:00 CDT 2064 So it's adjusting it for daylight savings time, and breaking. Sigh. _Why_ are we doing this date normalization checking thing again? It's kinda brittle. I'm starting to remember why this got pushed onto the todo stack. (Which is really a todo heap with a leaking problem.) Rob ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
On 12/30/2016 01:39 PM, enh wrote: > 1928-04-26 17:31:55.746667836 18446744072394174731 Really we can partially blame posix here for not specifying whether time_t is signed or unsigned. (If it's unsigned it can't represent times before January 1, 1970, as the code on the left is doing. And there _are_ times before then. So I think we have to treat it as signed and go "32 bit timestamps gotta go away before 2038".) Linus' opinion on unsigned time_t is here (spoiler: it's "no"): https://lkml.org/lkml/2011/8/31/246 > two patches attached. ... > the other > removes void* casts unnecessary since POSIX 2008 and fixes the > strftime buffer length argument. Why did you remove the comment block in the second patch? (Is it wrong?) Rob ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
I have negotiated a 3 day weekend for the holidays! Starting today. Ok, catching up... 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. 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.) /me goes down tangent rathole debugging why. (THIS is why I need to finish mkroot and get a toybox test environment set up that can test stuff requiring root access under qemu under a known root filesystem and kernel config. Is my code broken, or does strptime not parse negative numerical arguments for %s format?) (Answer: musl doesn't implement %s at all, and glibc doesn't allow the %s value it converts to be negative. And of course posix doesn't specify signed OR unsigned for time_t at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html because actually providing enough detail to implement things would be _useful_.) > two patches attached. one avoids sign extension for all calls to > `out`, fixing %Z for systems with a signed 32-bit time_t. The 0001-Avoid* patch only has the first hunk, which defines two macros there are never used and renames a function but not its users. >> This seems suspiciously large and I'm wondering what the valid range for >> this value is. I think we all do at this point. Rob ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] Stat %Z - What are valid values?
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.) https://android.googlesource.com/platform/external/toybox/+/android-6.0.1_r77/toys/other/stat.c doesn't look to different from today. with 64-bit toybox: angler:/ # date 06022064 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 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 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 two patches attached. one avoids sign extension for all calls to `out`, fixing %Z for systems with a signed 32-bit time_t. the other removes void* casts unnecessary since POSIX 2008 and fixes the strftime buffer length argument. %z is still broken for systems with signed 32-bit time_t, but i think that's just inherent on such systems. On Fri, Dec 30, 2016 at 9:28 AM, darkenwrote: > I've seen a value of "18446744072363093454" for stat %Z (seconds since > epoch), for some files on a users device (Android 6.01). > > This seems suspiciously large and I'm wondering what the valid range for > this value is. > What range is valid for the filesystem to return and what value range can > toybox handle? > > ~Matthias > > ___ > Toybox mailing list > Toybox@lists.landley.net > http://lists.landley.net/listinfo.cgi/toybox-landley.net > -- Elliott Hughes - http://who/enh - http://jessies.org/~enh/ Android native code/tools questions? Mail me/drop by/add me as a reviewer. From be5dd0c57df9d35bff7671c897e0b2dd384bdb84 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 30 Dec 2016 11:24:25 -0800 Subject: [PATCH] Avoid sign extension in stat.c. --- toys/other/stat.c | 16 +--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/toys/other/stat.c b/toys/other/stat.c index 9d64579..63dfba8 100644 --- a/toys/other/stat.c +++ b/toys/other/stat.c @@ -50,9 +50,19 @@ GLOBALS( int patlen; ) -// Force numeric output to long long instead of manually typecasting everything -// and safely parse length prefix -static void out(char c, long long val) +// Force numeric output to unsigned long long instead of manually typecasting +// everything. Takes unsigned because no struct stat field can be negative, +// and in combination with the add_unsigned macro this lets us avoid +// accidental sign extension of signed fields (time_t on LP32, say). +// We also handle length prefixes here rather than repeating that everywhere. +#define out(out_c, out_val) uout(out_c, add_unsigned(out_val)) +#define add_unsigned(x) \ + (sizeof(x) == sizeof(char) ? (unsigned char)(x) : \ + sizeof(x) == sizeof(short) ? (unsigned short)(x) : \ + sizeof(x) == sizeof(int) ? (unsigned int)(x) : \ + sizeof(x) == sizeof(long) ? (unsigned long)(x) : \ + (unsigned long long)(x)) +static void uout(char c, unsigned long long val) { sprintf(toybuf, "%.*sll%c", TT.patlen, TT.pattern, c); printf(toybuf, val); -- 2.8.0.rc3.226.g39d4020 From 1c4a7a8ac7ff68e07df91f5822dd8145229e4bf9 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 30 Dec 2016 11:19:08 -0800 Subject: [PATCH] Remove unnecessary casts in stat.c, fix a claimed buffer length. POSIX does have a name for the struct timespec in struct stat. --- toys/other/stat.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/toys/other/stat.c b/toys/other/stat.c index b998a0e..9d64579 100644 --- a/toys/other/stat.c +++ b/toys/other/stat.c @@ -65,14 +65,10 @@ static void strout(char *val) printf(toybuf, val); } -// Note: the atime, mtime, and ctime fields in struct stat are the start -// of embedded struct