You convinced me inetutils (and many other programs) has real bugs related to ctime today that should be fixed. Now I want to figure out what the best fix to existing code is.
Paul Eggert <egg...@cs.ucla.edu> writes: >> Another idea is to have gnulib's ctime augment the C standard to have >> ctime not be undefined but to return shorter and longer strings, which I >> believe is still consistent with the C standard? > > I would look askance at any Gnulib implementation of ctime that does > this sort of thing. The ctime API is so poorly designed that callers > should use some other API. This is partly why C23 is deprecating > ctime. Gnulib shouldn't encourage ctime's continued use. If gnulib provides a simple to use replacement with clear documented semantics and interface, and a clear upgrade path from current ctime, it seems okay to give up on trying to use the ctime API. Perhaps more than one upgrade path is needed, to accomodate different situations: the inetutils examples illustrate some different needs. If we do a good job here, it may serve as a template solution for this problem elsewhere. I see some systems migrate 32-bit time_t to 64-bit time_t, and if not done carefully, that may introduce reliance on undefined behaviour for years <1000 and >9999 when calling ctime that wasn't there before. > Perhaps we could a new module c_nstrftime, which acts like nstrftime > but operates in the C locale. That should suffice to replace all uses > of ctime relatively easily. Yes, although I would prefer a wrapper to hide the complex strftime format string needed. How about the API below? I'm not confident about the timezone handling: maybe it should set the tzset variables? And maybe a c_nctime_r would be useful to provide the timezone TZ to use? I'm also not certain about year 0 handling. /* Convert TIMEP representing the number of seconds elapsed since epoch, 1970-01-01 00:00:00 +0000 (UTC), to a fixed locale-independent string such as "Wed Jun 30 21:49:08 1993\n" using abbreviations for the days of the week as "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", and "Sat" and abbreviations for the months as "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", and "Dec". The function does not set the external variables tzname, timezone or daylight, see tzset(3). The output is copied into STR which must have room for at least LEN bytes. For years 1000 to 9999 inclusive the needed length will be 26 characters including the final NUL byte, but the required length may be shorter for years < 1000 and larger for years > 9999. The years are not padded with whitespace or zeros, so valid outputs include strings such as "Wed Jun 30 21:49:08 623\n" for years <1000 and for years >9999 strings such as "Wed Jun 30 21:49:08 11147\n" and for negative years strings such as "Wed Jun 30 21:49:08 -42\n". The preloptic Gregorian calendar is used for all years, to cover years before the Gregorian calendar was adopted; and for years before 1 the ISO 8601 approach to have years 2, 1, 0, -1, and so on is used instead of having 2 BC, 1 BC, AD 1, AD 2. If TIMEP cannot be converted into a string of size LEN, NULL is returned and errno is set to an error, otherwise on success STR is returned. */ char *c_ctime_r (time_t timep, char *str, size_t len); /Simon
signature.asc
Description: PGP signature