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
This commit is contained in:
Patsy Griffin 2025-06-25 17:24:54 -04:00
parent 6ee4fc612a
commit 485889d11c
6 changed files with 504 additions and 1 deletions

View File

@ -0,0 +1,173 @@
commit e541b219854e6be90b5628f88cd62edb44c9e9f2
Author: Alejandro Colomar <alx@kernel.org>
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: <https://lore.kernel.org/linux-man/20240823131024.GD2713@cventin.lip.ens-lyon.fr/T/#t>
Link: <https://lore.kernel.org/linux-man/6un6baaq5tez23irtycuvzqtuh7a4sdrf2px7tnyb3y6iqoxmq@2ofln4cd27ep/T/#t>
Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3147.txt>
Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3148.doc>
Link: <https://austingroupbugs.net/view.php?id=1614>
Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#subsubsection.7.29.2.3>
Reported-by: Paul Eggert <eggert@cs.ucla.edu>
Cc: Vincent Lefevre <vincent@vinc17.net>
Cc: DJ Delorie <dj@redhat.com>
Cc: Carlos O'Donell <carlos@redhat.com>
Cc: Xi Ruoyao <xry111@xry111.site>
Cc: Brian Inglis <Brian.Inglis@SystematicSW.ab.ca>
Cc: "Robert C. Seacord" <rcseacord@gmail.com>
Cc: Jens Gustedt <jens.gustedt@inria.fr>
Cc: Robert Elz <kre@munnari.oz.au>
Cc: Andrew Josey <ajosey@opengroup.org>
Cc: Geoff Clare <gwc@opengroup.org>
Cc: Hans Åberg <haberg-1@telia.com>
Cc: GNU C Library <libc-alpha@sourceware.org>
Cc: Austin Group <austin-group-l@opengroup.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
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 <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+\&
+#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),

View File

@ -0,0 +1,32 @@
commit 6a7f1461b0e5474d50ef1920558dec103c0c058f
Author: Alejandro Colomar <alx@kernel.org>
Date: Sat Aug 24 00:20:49 2024 +0200
ctime.3: Move NOTES to a subsection within CAVEATS
Signed-off-by: Alejandro Colomar <alx@kernel.org>
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

View File

@ -0,0 +1,44 @@
From f1016b60769174da8e396e30fd25f58bb58d4232 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
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 <fweimer@redhat.com>
Message-ID: <87o75chpwb.fsf@oldenburg.str.redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
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

View File

@ -0,0 +1,76 @@
From 9fdca71e4aba3605caa88b0c9eff3dc2c3f6fcfe Mon Sep 17 00:00:00 2001
From: DJ Delorie <dj@redhat.com>
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: <https://www.redhat.com/en/blog/brief-history-mktime>
Cc: Paul Eggert <eggert@cs.ucla.edu>
Cc: Carlos O'Donell <carlos@redhat.com>
Signed-off-by: DJ Delorie <dj@redhat.com>
Message-ID: <xncylqiznb.fsf@greed.delorie.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
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

View File

@ -0,0 +1,162 @@
commit bd576aaf5fce40100133c1d48c02eacbf25594c8
Author: Alejandro Colomar <alx@kernel.org>
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: <https://www.redhat.com/en/blog/brief-history-mktime>
Cc: DJ Delorie <dj@redhat.com>
Cc: Carlos O'Donell <carlos@redhat.com>
Cc: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
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 <err.h>
+#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <time.h>
\&
#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

View File

@ -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 ##