From 485889d11c18d16e28eea168768dd1d624a8b8b3 Mon Sep 17 00:00:00 2001 From: Patsy Griffin Date: Wed, 25 Jun 2025 17:24:54 -0400 Subject: [PATCH] Add RTLD_DI_PHDR to dlinfo(3) man page. Provide more details on using mktime(3) in the manpage. Resolves: RHEL-61159 Resolves: RHEL-61136 --- ...ment-how-to-check-errors-from-mktime.patch | 173 ++++++++++++++++++ ...NOTES-to-a-subsection-within-CAVEATS.patch | 32 ++++ ....3-Document-the-RTLD_DI_PHDR-request.patch | 44 +++++ ...Add-note-about-tm_isdst-handling-in-.patch | 76 ++++++++ ...to-detect-invalid-or-ambiguous-times.patch | 162 ++++++++++++++++ man-pages.spec | 18 +- 6 files changed, 504 insertions(+), 1 deletion(-) create mode 100644 0000-ctime.3-Document-how-to-check-errors-from-mktime.patch create mode 100644 0001-ctime.3-Move-NOTES-to-a-subsection-within-CAVEATS.patch create mode 100644 0001-dlinfo.3-Document-the-RTLD_DI_PHDR-request.patch create mode 100644 0002-ctime.3-CAVEATS-Add-note-about-tm_isdst-handling-in-.patch create mode 100644 0003-ctime.3-EXAMPLES-Document-how-to-detect-invalid-or-ambiguous-times.patch diff --git a/0000-ctime.3-Document-how-to-check-errors-from-mktime.patch b/0000-ctime.3-Document-how-to-check-errors-from-mktime.patch new file mode 100644 index 0000000..8688747 --- /dev/null +++ b/0000-ctime.3-Document-how-to-check-errors-from-mktime.patch @@ -0,0 +1,173 @@ +commit e541b219854e6be90b5628f88cd62edb44c9e9f2 +Author: Alejandro Colomar +Date: Fri Aug 23 14:34:00 2024 +0200 + + ctime.3: Document how to check errors from mktime(3) + + -1 is a valid successful time_t, for one second before the Epoch. And + mktime(3) is allowed (like most libc calls) to set errno on success. + This makes it impossible to determine errors from the return value or + errno. + + ISO C specifies that tp->tm_wday is unmodified after a failed call, and + puts an example where this is used to determine errors. It is indeed + the only way to check for errors from this call. + + Document this detail in the RETURN VALUE section, add a CAVEATS section + that warns about this, and write an example program that shows how to + properly call this function. + + Most code I've been able to find in several search engines either + doesn't check for errors after mktime(3), or checks them incorrectly, so + this documentation should help fix those. + + This is guaranteed since ISO C23 and POSIX.1-2024. Prior to those + standards, there was no standard way to check for errors. However, + there are no known implementations that do not conform to this. + + Link: + Link: + Link: + Link: + Link: + Link: + Reported-by: Paul Eggert + Cc: Vincent Lefevre + Cc: DJ Delorie + Cc: Carlos O'Donell + Cc: Xi Ruoyao + Cc: Brian Inglis + Cc: "Robert C. Seacord" + Cc: Jens Gustedt + Cc: Robert Elz + Cc: Andrew Josey + Cc: Geoff Clare + Cc: Hans Ã…berg + Cc: GNU C Library + Cc: Austin Group + Signed-off-by: Alejandro Colomar + +Conflicts: + Minor wording differences + +diff -Nrup a/man3/ctime.3 b/man3/ctime.3 +--- a/man3/ctime.3 2023-04-02 20:27:24.000000000 -0400 ++++ b/man3/ctime.3 2025-06-18 09:39:54.782440669 -0400 +@@ -247,7 +247,10 @@ expressed as a value of type + On error, + .BR mktime () + returns the value +-.IR "(time_t)\ \-1" . ++.IR "(time_t)\ \-1" , ++and leaves the ++.I tm->tm_wday ++member unmodified. + The remaining functions return NULL on error. + On error, + .I errno +@@ -400,6 +403,105 @@ a broken-down time structure and an arra + Execution of any of the functions may overwrite the information returned + in either of these objects by any of the other functions." + This can occur in the glibc implementation. ++.SH CAVEATS ++.SS mktime() ++.I (time_t) \-1 ++can represent a valid time ++(one second before the Epoch). ++To determine whether ++.BR mktime () ++failed, ++one must use the ++.I tm->tm_wday ++field. ++See the example program in EXAMPLES. ++.SH EXAMPLES ++The following shell session shows sample runs of the program: ++.P ++.in +4n ++.EX ++.RB $\~ "TZ=UTC ./a.out 1969 12 31 23 59 59 0" ; ++\-1 ++$ ++.RB $\~ "export TZ=Europe/Madrid" ; ++$ ++.RB $\~ "./a.out 2147483647 2147483647 00 00 00 00 -1" ; ++a.out: mktime: Value too large for defined data type ++$ ++.RB $\~ "./a.out 2024 08 23 00 17 53 \-1" ; ++1724365073 ++.RB $\~ "./a.out 2024 08 23 00 17 53 0" ; ++1724368673 ++.RB $\~ "./a.out 2024 08 23 00 17 53 1" ; ++1724365073 ++$ ++.RB $\~ "./a.out 2024 02 23 00 17 53 \-1" ; ++1708643873 ++.RB $\~ "./a.out 2024 02 23 00 17 53 0" ; ++1708643873 ++.RB $\~ "./a.out 2024 02 23 00 17 53 1" ; ++1708640273 ++$ ++.RB $\~ "./a.out 2023 03 26 02 17 53 \-1" ; ++1679793473 ++$ ++.RB $\~ "./a.out 2023 10 29 02 17 53 \-1" ; ++1698542273 ++.RB $\~ "./a.out 2023 10 29 02 17 53 0" ; ++1698542273 ++.RB $\~ "./a.out 2023 10 29 02 17 53 1" ; ++1698538673 ++$ ++.RB $\~ "./a.out 2023 02 29 12 00 00 \-1" ; ++1677668400 ++.EE ++.SS Program source: mktime.c ++\& ++.\" SRC BEGIN (mktime.c) ++.EX ++#include ++#include ++#include ++#include ++#include ++\& ++#define is_signed(T) ((T) \-1 < 1) ++\& ++int ++main(int argc, char *argv[]) ++{ ++ char **p; ++ time_t t; ++ struct tm tm; ++\& ++ if (argc != 8) { ++ fprintf(stderr, "Usage: %s yyyy mm dd HH MM SS isdst\[rs]n", argv[0]); ++ exit(EXIT_FAILURE); ++ } ++\& ++ p = &argv[1]; ++ tm.tm_year = atoi(*p++) \- 1900; ++ tm.tm_mon = atoi(*p++) \- 1; ++ tm.tm_mday = atoi(*p++); ++ tm.tm_hour = atoi(*p++); ++ tm.tm_min = atoi(*p++); ++ tm.tm_sec = atoi(*p++); ++ tm.tm_isdst = atoi(*p++); ++\& ++ tm.tm_wday = \-1; ++ t = mktime(&tm); ++ if (tm.tm_wday == \-1) ++ err(EXIT_FAILURE, "mktime"); ++\& ++ if (is_signed(time_t)) ++ printf("%jd\[rs]n", (intmax_t) t); ++ else ++ printf("%ju\[rs]n", (uintmax_t) t); ++\& ++ exit(EXIT_SUCCESS); ++} ++.EE ++.\" SRC END + .SH SEE ALSO + .BR date (1), + .BR gettimeofday (2), diff --git a/0001-ctime.3-Move-NOTES-to-a-subsection-within-CAVEATS.patch b/0001-ctime.3-Move-NOTES-to-a-subsection-within-CAVEATS.patch new file mode 100644 index 0000000..3dcd500 --- /dev/null +++ b/0001-ctime.3-Move-NOTES-to-a-subsection-within-CAVEATS.patch @@ -0,0 +1,32 @@ +commit 6a7f1461b0e5474d50ef1920558dec103c0c058f +Author: Alejandro Colomar +Date: Sat Aug 24 00:20:49 2024 +0200 + + ctime.3: Move NOTES to a subsection within CAVEATS + + Signed-off-by: Alejandro Colomar + +Conflicts: + Minor wording differences + +diff -Nrup a/man3/ctime.3 b/man3/ctime.3 +--- a/man3/ctime.3 2025-06-18 16:14:51.847871469 -0400 ++++ b/man3/ctime.3 2025-06-18 16:25:22.406139771 -0400 +@@ -374,7 +374,8 @@ POSIX.1-2001. + POSIX.1-2001. + Marked obsolete in POSIX.1-2008 (recommending + .BR strftime (3)). +-.SH NOTES ++.SH CAVEATS ++.SS Thread safety + The four functions + .BR asctime (), + .BR ctime (), +@@ -403,7 +404,6 @@ a broken-down time structure and an arra + Execution of any of the functions may overwrite the information returned + in either of these objects by any of the other functions." + This can occur in the glibc implementation. +-.SH CAVEATS + .SS mktime() + .I (time_t) \-1 + can represent a valid time diff --git a/0001-dlinfo.3-Document-the-RTLD_DI_PHDR-request.patch b/0001-dlinfo.3-Document-the-RTLD_DI_PHDR-request.patch new file mode 100644 index 0000000..9aa9726 --- /dev/null +++ b/0001-dlinfo.3-Document-the-RTLD_DI_PHDR-request.patch @@ -0,0 +1,44 @@ +From f1016b60769174da8e396e30fd25f58bb58d4232 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Wed, 28 Aug 2024 13:01:56 +0200 +Subject: [PATCH] dlinfo.3: Document the RTLD_DI_PHDR request + +First added in glibc 2.36, backported upstream to glibc 2.34, +so mention 2.34.1 for the first version. + +Signed-off-by: Florian Weimer +Message-ID: <87o75chpwb.fsf@oldenburg.str.redhat.com> +Signed-off-by: Alejandro Colomar +--- + man/man3/dlinfo.3 | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/man3/dlinfo.3 b/man3/dlinfo.3 +index bc331dc..a77e514 100644 +--- a/man3/dlinfo.3 ++++ b/man3/dlinfo.3 +@@ -194,10 +194,23 @@ If this object does not define a PT_TLS segment, + or if the calling thread has not allocated a block for it, + NULL is placed in + .IR *info . ++.TP ++.BR RTLD_DI_PHDR " (\fIconst ElfW(Phdr *)\fP, since glibc 2.34.1)" ++.\" glibc commit d056c212130280c0a54d9a4f72170ec621b70ce5 (2.36) ++.\" glibc commit 28ea43f8d64f0dd1f2de75525157730e1532e600 (2.35.1) ++.\" glibc commit 91c2e6c3db44297bf4cb3a2e3c40236c5b6a0b23 (2.34.1) ++Obtain the address of this shared object's program header and place it ++in ++.IR *info . ++This ++.B dlinfo ++call returns the number of program headers in the shared object. + .SH RETURN VALUE + On success, + .BR dlinfo () +-returns 0. ++returns 0 ++(if not specified explicitly), ++or a positive value corresponding to the request. + On failure, it returns \-1; the cause of the error can be diagnosed using + .BR dlerror (3). + .SH ATTRIBUTES diff --git a/0002-ctime.3-CAVEATS-Add-note-about-tm_isdst-handling-in-.patch b/0002-ctime.3-CAVEATS-Add-note-about-tm_isdst-handling-in-.patch new file mode 100644 index 0000000..3b5c0ce --- /dev/null +++ b/0002-ctime.3-CAVEATS-Add-note-about-tm_isdst-handling-in-.patch @@ -0,0 +1,76 @@ +From 9fdca71e4aba3605caa88b0c9eff3dc2c3f6fcfe Mon Sep 17 00:00:00 2001 +From: DJ Delorie +Date: Thu, 29 Aug 2024 21:10:32 -0400 +Subject: [PATCH] ctime.3: CAVEATS: Add note about tm_isdst handling in + mktime(3) + +Handling of "invalid" values for tm_isdst is not clearly specified +in any standard, and implementations vary as to how they react when you +(for example) pass tm_isdst=1 at a time when DST is not in effect. +Add a note about this, and a suggestion for a workaround. + +I go into further detail about this in the link below. + +Link: +Cc: Paul Eggert +Cc: Carlos O'Donell +Signed-off-by: DJ Delorie +Message-ID: +Signed-off-by: Alejandro Colomar +--- + man/man3/ctime.3 | 39 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/man3/ctime.3 b/man3/ctime.3 +index 0ad2b530f..53abab6d9 100644 +--- a/man3/ctime.3 ++++ b/man3/ctime.3 +@@ -427,6 +427,45 @@ one must use the + .I tm->tm_wday + field. + See the example program in EXAMPLES. ++.P ++The handling of a non-negative ++.I tm_isdst ++in ++.BR mktime () ++is poorly specified, ++and passing a value that is incorrect for the time specified ++yields unspecified results. ++Since ++.BR mktime () ++is one of the few functions that knows when DST is in effect, ++providing a correct value may be difficult. ++One workaround for this is to call ++.BR mktime () ++twice, ++once with ++.I tm_isdst ++set to zero, ++and once with ++.I tm_isdst ++set to a positive value, ++and discarding the results from the call that changes it. ++If neither call changes ++.I tm_isdst ++then the time specified probably happens during a fall-back period ++where DST begins or ends, ++and both results are valid ++but represent two different times. ++If both calls change it, that could indicate a fall-forward transition, ++or some other reason why the time specified does not exist. ++.P ++The specification of time zones and daylight saving time ++are up to regional governments, change often, ++and may include discontinuities beyond ++.IR mktime 's ++ability to document a result. ++For example, a change in the timezone definition ++may cause a clock time to be repeated or skipped ++without a corresponding DST change. + .SH EXAMPLES + The following shell session shows sample runs of the program: + .P +-- +2.46.1 + diff --git a/0003-ctime.3-EXAMPLES-Document-how-to-detect-invalid-or-ambiguous-times.patch b/0003-ctime.3-EXAMPLES-Document-how-to-detect-invalid-or-ambiguous-times.patch new file mode 100644 index 0000000..b7cd11b --- /dev/null +++ b/0003-ctime.3-EXAMPLES-Document-how-to-detect-invalid-or-ambiguous-times.patch @@ -0,0 +1,162 @@ +commit bd576aaf5fce40100133c1d48c02eacbf25594c8 +Author: Alejandro Colomar +Date: Sat Aug 24 00:51:55 2024 +0200 + + ctime.3: EXAMPLES: Document how to detect invalid or ambiguous times + + This example documents how to detect some corner cases of mktime(3), + such as DST transitions and other jumps in the calendar. + + Link: + Cc: DJ Delorie + Cc: Carlos O'Donell + Cc: Paul Eggert + Signed-off-by: Alejandro Colomar + +diff --git a/man3/ctime.3 b/man/man3/ctime.3 +index 53abab6d9..acd6f1565 100644 +--- a/man3/ctime.3 ++++ b/man3/ctime.3 +@@ -467,6 +467,14 @@ For example, a change in the timezone definition + may cause a clock time to be repeated or skipped + without a corresponding DST change. + .SH EXAMPLES ++The program below defines a wrapper that ++allows detecting invalid and ambiguous times, ++with ++.B EINVAL ++and ++.BR ENOTUNIQ , ++respectively. ++.P + The following shell session shows sample runs of the program: + .P + .in +4n +@@ -482,6 +490,7 @@ $ + .RB $\~ "./a.out 2024 08 23 00 17 53 \-1" ; + 1724365073 + .RB $\~ "./a.out 2024 08 23 00 17 53 0" ; ++a.out: my_mktime: Invalid argument + 1724368673 + .RB $\~ "./a.out 2024 08 23 00 17 53 1" ; + 1724365073 +@@ -491,12 +500,15 @@ $ + .RB $\~ "./a.out 2024 02 23 00 17 53 0" ; + 1708643873 + .RB $\~ "./a.out 2024 02 23 00 17 53 1" ; ++a.out: my_mktime: Invalid argument + 1708640273 + $ + .RB $\~ "./a.out 2023 03 26 02 17 53 \-1" ; ++a.out: my_mktime: Invalid argument + 1679793473 + $ + .RB $\~ "./a.out 2023 10 29 02 17 53 \-1" ; ++a.out: my_mktime: Name not unique on network + 1698542273 + .RB $\~ "./a.out 2023 10 29 02 17 53 0" ; + 1698542273 +@@ -504,6 +516,7 @@ $ + 1698538673 + $ + .RB $\~ "./a.out 2023 02 29 12 00 00 \-1" ; ++a.out: my_mktime: Invalid argument + 1677668400 + .EE + .SS Program source: mktime.c +@@ -511,13 +524,17 @@ $ + .\" SRC BEGIN (mktime.c) + .EX + #include ++#include + #include + #include + #include ++#include + #include + \& + #define is_signed(T) ((T) \-1 < 1) + \& ++time_t my_mktime(struct tm *tp); ++\& + int + main(int argc, char *argv[]) + { +@@ -539,10 +556,13 @@ main(int argc, char *argv[]) + tm.tm_sec = atoi(*p++); + tm.tm_isdst = atoi(*p++); + \& ++ errno = 0; + tm.tm_wday = \-1; +- t = mktime(&tm); ++ t = my_mktime(&tm); + if (tm.tm_wday == \-1) + err(EXIT_FAILURE, "mktime"); ++ if (errno == EINVAL || errno == ENOTUNIQ) ++ warn("my_mktime"); + \& + if (is_signed(time_t)) + printf("%jd\[rs]n", (intmax_t) t); +@@ -551,6 +571,62 @@ main(int argc, char *argv[]) + \& + exit(EXIT_SUCCESS); + } ++\& ++time_t ++my_mktime(struct tm *tp) ++{ ++ int e, isdst; ++ time_t t; ++ struct tm tm; ++ unsigned char wday[sizeof(tp\->tm_wday)]; ++\& ++ e = errno; ++\& ++ tm = *tp; ++ isdst = tp\->tm_isdst; ++\& ++ memcpy(wday, &tp\->tm_wday, sizeof(wday)); ++ tp\->tm_wday = \-1; ++ t = mktime(tp); ++ if (tp\->tm_wday == \-1) { ++ memcpy(&tp\->tm_wday, wday, sizeof(wday)); ++ return \-1; ++ } ++\& ++ if (isdst == \-1) ++ tm.tm_isdst = tp\->tm_isdst; ++\& ++ if ( tm.tm_sec != tp\->tm_sec ++ || tm.tm_min != tp\->tm_min ++ || tm.tm_hour != tp\->tm_hour ++ || tm.tm_mday != tp\->tm_mday ++ || tm.tm_mon != tp\->tm_mon ++ || tm.tm_year != tp\->tm_year ++ || tm.tm_isdst != tp\->tm_isdst) ++ { ++ errno = EINVAL; ++ return t; ++ } ++\& ++ if (isdst != \-1) ++ goto out; ++\& ++ tm = *tp; ++ tm.tm_isdst = !tm.tm_isdst; ++\& ++ tm.tm_wday = \-1; ++ mktime(&tm); ++ if (tm.tm_wday == \-1) ++ goto out; ++\& ++ if (tm.tm_isdst != tp\->tm_isdst) { ++ errno = ENOTUNIQ; ++ return t; ++ } ++out: ++ errno = e; ++ return t; ++} + .EE + .\" SRC END + .SH SEE ALSO diff --git a/man-pages.spec b/man-pages.spec index 4926969..571d547 100644 --- a/man-pages.spec +++ b/man-pages.spec @@ -51,13 +51,29 @@ BuildArch: noarch # https://bugzilla.kernel.org/show_bug.cgi?id=53781 Patch21: man-pages-3.42-close.patch +# Upstream commit: https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit/?id=f1016b60769174da8e396e30fd25f58bb58d4232 +# Resolves: RHEL-53953 +Patch22: 0001-dlinfo.3-Document-the-RTLD_DI_PHDR-request.patch + +# Upstream patches to provide more info on mktime(). +# Resolves: RHEL-58342 +Patch23: 0000-ctime.3-Document-how-to-check-errors-from-mktime.patch +Patch24: 0001-ctime.3-Move-NOTES-to-a-subsection-within-CAVEATS.patch +Patch25: 0002-ctime.3-CAVEATS-Add-note-about-tm_isdst-handling-in-.patch +Patch26: 0003-ctime.3-EXAMPLES-Document-how-to-detect-invalid-or-ambiguous-times.patch + %description A large collection of manual pages from the Linux Documentation Project (LDP). %prep %setup -q -a 1 -%patch -P 21 -p1 +%patch -p1 -P 21 +%patch -p1 -P 22 +%patch -p1 -P 23 +%patch -p1 -P 24 +%patch -p1 -P 25 +%patch -p1 -P 26 ## Remove man pages we are not going to use ##