Both the C standard and POSIX state that mktime() returns -1 on failure; POSIX additionally states that it sets errno. However, since -1 is also a valid result (representing 23:59:59 UTC on 1969-12-31) and POSIX never guarantees that a successful call does not modify errno, it seems to me that the only reliable way to determine whether mktime() succeeded, within the bounds of the aforementioned standards, is to set tm_wday or tm_yday to an out-of-bounds value (e.g. -1) prior to calling mktime() and check whether it has been modified on return. As far as I can tell, this has been the case ever since mktime() was introduced in POSIX.1 in 1988 and XPG3 and ANSI C in 1989. Am I wrong? Would it be a mistake to state this outright in the appropriate manual page? DES -- Dag-Erling Smørgrav - des@des.no
Dag-Erling Smrgrav via tz said:
Both the C standard and POSIX state that mktime() returns -1 on failure; POSIX additionally states that it sets errno. However, since -1 is also a valid result (representing 23:59:59 UTC on 1969-12-31) and POSIX never guarantees that a successful call does not modify errno, it seems to me that the only reliable way to determine whether mktime() succeeded, within the bounds of the aforementioned standards, is to set tm_wday or tm_yday to an out-of-bounds value (e.g. -1) prior to calling mktime() and check whether it has been modified on return.
That doesn't prove things, because it could be set before an error was determined. Library functions and system calls never set errno to 0. So the usual answer is to set errno to 0 before the call and see if it's still 0 afterwards. If so, there was no error. If not, there might have been an error. I don't think there's any way to determine if return -1 and errno changed indicates an error or not. -- Clive D.W. Feather | If you lie to the compiler, Email: clive@davros.org | it will get its revenge. Web: http://www.davros.org | - Henry Spencer Mobile: +44 7973 377646
"Clive D.W. Feather via tz" <tz@iana.org> writes:
Dag-Erling Smørgrav <des@des.no> writes:
[...] POSIX never guarantees that a successful call does not modify errno [...] Library functions and system calls never set errno to 0. So the usual answer is to set errno to 0 before the call and see if it's still 0 afterwards.
See above, and try this: struct tm tm = { .tm_mday = 1, .tm_year = 69 }; errno = 0; printf("%ld %d\n", mktime(&tm), errno); DES -- Dag-Erling Smørgrav - des@des.no
Dag-Erling Smrgrav said:
"Clive D.W. Feather via tz" <tz@iana.org> writes:
Dag-Erling Smørgrav <des@des.no> writes:
[...] POSIX never guarantees that a successful call does not modify errno [...] Library functions and system calls never set errno to 0. So the usual answer is to set errno to 0 before the call and see if it's still 0 afterwards.
See above, and try this:
struct tm tm = { .tm_mday = 1, .tm_year = 69 }; errno = 0; printf("%ld %d\n", mktime(&tm), errno);
There is no requirement in the C99 Standard (I dropped out of WG14 shortly after) that the call to mktime is made before the value of errno is read. -- Clive D.W. Feather | If you lie to the compiler, Email: clive@davros.org | it will get its revenge. Web: http://www.davros.org | - Henry Spencer Mobile: +44 7973 377646
"Clive D.W. Feather via tz" <tz@iana.org> writes:
There is no requirement in the C99 Standard (I dropped out of WG14 shortly after) that the call to mktime is made before the value of errno is read.
True, I was a little hasty in abbreviating my example, but beside the point, as you'd realize if you'd bothered to try it. struct tm tm = { .tm_mday = 1, .tm_year = 69 }; errno = 0; time_t ret = mktime(&tm); printf("%ld %d\n", (long)ret, errno); DES -- Dag-Erling Smørgrav - des@des.no
On 2024-03-25 15:08, Dag-Erling Smørgrav via tz wrote:
"Clive D.W. Feather via tz" <tz@iana.org> writes:
There is no requirement in the C99 Standard (I dropped out of WG14 shortly after) that the call to mktime is made before the value of errno is read.
True, I was a little hasty in abbreviating my example, but beside the point, as you'd realize if you'd bothered to try it.
struct tm tm = { .tm_mday = 1, .tm_year = 69 }; errno = 0; time_t ret = mktime(&tm); printf("%ld %d\n", (long)ret, errno);
If you want others to run code, you should provide a complete program. It would be more informative to state the platform and compiler you used, show the results you got, and explain what you think it means. -- Take care. Thanks, Brian Inglis Calgary, Alberta, Canada La perfection est atteinte Perfection is achieved non pas lorsqu'il n'y a plus rien à ajouter not when there is no more to add mais lorsqu'il n'y a plus rien à retirer but when there is no more to cut -- Antoine de Saint-Exupéry
"brian.inglis--- via tz" <tz@iana.org> writes:
It would be more informative to state the platform and compiler you used, show the results you got, and explain what you think it means.
I didn't expect my audience to be wilfully obtuse. As I've already stated and emphasized, POSIX does not guarantee or require that errno is not modified by a successful call. Given the input from my example, tzcode will set errno to EOVERFLOW before returning successfully. DES -- Dag-Erling Smørgrav - des@des.no
On 2024-03-25 19:53, Dag-Erling Smørgrav wrote:
"brian.inglis--- via tz" <tz@iana.org> writes:
It would be more informative to state the platform and compiler you used, show the results you got, and explain what you think it means.
I didn't expect my audience to be wilfully obtuse. As I've already stated and emphasized, POSIX does not guarantee or require that errno is not modified by a successful call. Given the input from my example, tzcode will set errno to EOVERFLOW before returning successfully.
So you are running tzcode mktime on some unspecified platform, compiler, and library, and that implementation happens to return that result, unless it happens that implementation's printf set errno to EOVERFLOW, before printing it. Other platforms, libraries, and mktime implementations may produce different results: one platform I tested set errno = 2 ENOENT as posixrules is not installed, but time_t was as expected. -- Take care. Thanks, Brian Inglis Calgary, Alberta, Canada La perfection est atteinte Perfection is achieved non pas lorsqu'il n'y a plus rien à ajouter not when there is no more to add mais lorsqu'il n'y a plus rien à retirer but when there is no more to cut -- Antoine de Saint-Exupéry
I didn't expect my audience to be wilfully obtuse.
I didn't expect to receive insults on this mailing list. Please, keep your responses civil, and explain any mistakes in proposed solutions without resorting to personal attacks. Tim ________________________________ From: tz <tz-bounces@iana.org> on behalf of Dag-Erling Smørgrav via tz <tz@iana.org> Sent: 26 March 2024 01:53 To: brian.inglis--- via tz <tz@iana.org> Subject: Re: [tz] mktime() clarification WARNING: This email has originated from outside of EkkoSense. Please treat any links or attachments with caution. "brian.inglis--- via tz" <tz@iana.org> writes:
It would be more informative to state the platform and compiler you used, show the results you got, and explain what you think it means.
I didn't expect my audience to be wilfully obtuse. As I've already stated and emphasized, POSIX does not guarantee or require that errno is not modified by a successful call. Given the input from my example, tzcode will set errno to EOVERFLOW before returning successfully. DES -- Dag-Erling Smørgrav - des@des.no ****************************************************************** The information in this E-Mail is confidential and may be legally privileged. It may not represent the views of EkkoSense. It is intended solely for the addressees. Access to this E-Mail by anyone else is unauthorised. If you are not the intended recipient, any disclosure, copying, distribution or any action taken or omitted to be taken in reliance on it, is prohibited and may be unlawful. Any unauthorised recipient should advise the sender immediately of the error in transmission. Unless specifically stated otherwise, this email (or any attachments to it) is not an offer capable of acceptance or acceptance of an offer and it does not form part of a binding contractual agreement. ******************************************************************
Dag-Erling Smørgrav wrote:
Both the C standard and POSIX state that mktime() returns -1 on failure; POSIX additionally states that it sets errno. However, since -1 is also a valid result (representing 23:59:59 UTC on 1969-12-31) and POSIX never guarantees that a successful call does not modify errno, it seems to me that the only reliable way to determine whether mktime() succeeded...
I could be wrong, but I have the impression that there are or have been a very few library functions over the years that *did* guarantee not to modify errno on success. I wish mktime was or could be made one of them -- that would seem to be an ideal way to resolve the return value ambiguity here.
On 3/25/24 12:16, Dag-Erling Smørgrav via tz wrote:
it seems to me that the only reliable way to determine whether mktime() succeeded, within the bounds of the aforementioned standards, is to set tm_wday or tm_yday to an out-of-bounds value (e.g. -1) prior to calling mktime()
That's what I do, and it works portably on all platforms I know of. In contrast, I doubt whether the errno=0 trick is portable. I installed the attached proposed patch to the documentation.
Paul Eggert via tz <tz@iana.org> writes:
That's what I do, and it works portably on all platforms I know of. In contrast, I doubt whether the errno=0 trick is portable.
Thank you. The errno=0 trick does not work with tzcode since timesub() can set errno to EOVERFLOW and time2sub() will adjust and recover, cf. https://github.com/eggert/tz/blob/2024a/localtime.c#L2060-L2064 and the elsewhere in this thread. DES -- Dag-Erling Smørgrav - des@des.no
Dag-Erling Smørgrav via tz <tz@iana.org> writes:
Thank you. The errno=0 trick does not work with tzcode since timesub() can set errno to EOVERFLOW and time2sub() will adjust and recover, cf. https://github.com/eggert/tz/blob/2024a/localtime.c#L2060-L2064 and the
missing: “example I provided"
elsewhere in this thread.
DES -- Dag-Erling Smørgrav - des@des.no
On 2024-03-25 19:52, Paul Eggert via tz wrote:
On 3/25/24 12:16, Dag-Erling Smørgrav via tz wrote:
it seems to me that the only reliable way to determine whether mktime() succeeded, within the bounds of the aforementioned standards, is to set tm_wday or tm_yday to an out-of-bounds value (e.g. -1) prior to calling mktime()
That's what I do, and it works portably on all platforms I know of. In contrast, I doubt whether the errno=0 trick is portable.
I installed the attached proposed patch to the documentation.
+To distinguish failure from a valid \-1 return, +you can set +.B tm_mday
.B tm_wday?
+or +.B tm_yday +to a negative value before calling
-- Take care. Thanks, Brian Inglis Calgary, Alberta, Canada La perfection est atteinte Perfection is achieved non pas lorsqu'il n'y a plus rien à ajouter not when there is no more to add mais lorsqu'il n'y a plus rien à retirer but when there is no more to cut -- Antoine de Saint-Exupéry
participants (6)
-
brian.inglis@systematicsw.ab.ca -
Clive D.W. Feather -
Dag-Erling Smørgrav -
Paul Eggert -
scs@eskimo.com -
Tim Hitchins