unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 1/7] login: Move gnu utmpx to default implementation
@ 2020-08-05 18:59 Adhemerval Zanella via Libc-alpha
  2020-08-05 18:59 ` [PATCH v2 2/7] Consolidate and simplify internal utmp definitions Adhemerval Zanella via Libc-alpha
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 18:59 UTC (permalink / raw)
  To: libc-alpha

It removes one indirection where generic implementation assumes that
utmp and utmpx might differ and allows the optimize the symbol alias
where getutmp is the same as getumpx.

Checked with make check run-built-tests=no on all afftected ABIs.
---
 .../gnu/bits => bits/types}/struct_utmpx.h    |  0
 {sysdeps/gnu/bits => bits}/utmpx.h            |  2 +-
 include/utmpx.h                               |  1 +
 login/Makefile                                |  2 +-
 login/getutmp.c                               | 34 ++++++++++++++++--
 login/getutmpx.c                              | 35 +------------------
 login/updwtmp.c                               | 11 +++++-
 {sysdeps/gnu => login}/utmpx.h                |  0
 sysdeps/gnu/getutmp.c                         | 34 ------------------
 sysdeps/gnu/getutmpx.c                        |  1 -
 sysdeps/gnu/updwtmp.c                         | 31 ----------------
 .../unix/sysv/linux/s390/s390-32/getutmp.c    | 21 ++++-------
 .../unix/sysv/linux/s390/s390-32/updwtmp.c    |  2 +-
 13 files changed, 54 insertions(+), 120 deletions(-)
 rename {sysdeps/gnu/bits => bits/types}/struct_utmpx.h (100%)
 rename {sysdeps/gnu/bits => bits}/utmpx.h (98%)
 create mode 100644 include/utmpx.h
 rename {sysdeps/gnu => login}/utmpx.h (100%)
 delete mode 100644 sysdeps/gnu/getutmp.c
 delete mode 100644 sysdeps/gnu/getutmpx.c
 delete mode 100644 sysdeps/gnu/updwtmp.c

diff --git a/sysdeps/gnu/bits/struct_utmpx.h b/bits/types/struct_utmpx.h
similarity index 100%
rename from sysdeps/gnu/bits/struct_utmpx.h
rename to bits/types/struct_utmpx.h
diff --git a/sysdeps/gnu/bits/utmpx.h b/bits/utmpx.h
similarity index 98%
rename from sysdeps/gnu/bits/utmpx.h
rename to bits/utmpx.h
index 12ee26871e..aecc433276 100644
--- a/sysdeps/gnu/bits/utmpx.h
+++ b/bits/utmpx.h
@@ -51,7 +51,7 @@ struct __exit_status
   };
 
 
-#include <bits/struct_utmpx.h>
+#include <bits/types/struct_utmpx.h>
 
 
 /* Values for the `ut_type' field of a `struct utmpx'.  */
diff --git a/include/utmpx.h b/include/utmpx.h
new file mode 100644
index 0000000000..cfe9b7c054
--- /dev/null
+++ b/include/utmpx.h
@@ -0,0 +1 @@
+#include <login/utmpx.h>
diff --git a/login/Makefile b/login/Makefile
index 758899900d..c61d1950bb 100644
--- a/login/Makefile
+++ b/login/Makefile
@@ -26,7 +26,7 @@ include ../Makeconfig
 headers	:= utmp.h bits/utmp.h lastlog.h pty.h \
 	   bits/types/struct_lastlog.h \
 	   bits/types/struct_utmp.h \
-	   bits/struct_utmpx.h
+	   bits/types/struct_utmpx.h
 
 routines := getlogin getlogin_r setlogin getlogin_r_chk \
 	    getutent getutent_r getutid getutline getutid_r getutline_r \
diff --git a/login/getutmp.c b/login/getutmp.c
index e9a5fe69a5..3058a93d1b 100644
--- a/login/getutmp.c
+++ b/login/getutmp.c
@@ -17,17 +17,47 @@
 
 #include <string.h>
 #include <utmp.h>
+#include <stddef.h>
+#define getutmpx __redirect_getutmpx
 #include <utmpx.h>
+#undef getutmpx
+
+#define CHECK_SIZE_AND_OFFSET(field) \
+  _Static_assert (sizeof ((struct utmp){0}.field)		\
+		  == sizeof ((struct utmpx){0}.field),		\
+		  "sizeof ((struct utmp){0}." #field " != "	\
+		  "sizeof ((struct utmpx){0}" #field);	\
+  _Static_assert (offsetof (struct utmp, field)			\
+		  == offsetof (struct utmpx, field),		\
+		  "offsetof (struct utmp, " #field ") != "	\
+		  "offsetof (struct utmpx, " #field ")");
+
+/* This ensure the getutmp to getutmpx alias is valid.  */
+_Static_assert (sizeof (struct utmp) == sizeof (struct utmpx),
+		"sizeof (struct utmp) != sizeof (struct utmpx)");
+CHECK_SIZE_AND_OFFSET (ut_type)
+CHECK_SIZE_AND_OFFSET (ut_pid)
+CHECK_SIZE_AND_OFFSET (ut_line)
+CHECK_SIZE_AND_OFFSET (ut_user)
+CHECK_SIZE_AND_OFFSET (ut_id)
+CHECK_SIZE_AND_OFFSET (ut_host)
+CHECK_SIZE_AND_OFFSET (ut_tv)
+
 
 /* Copy the information in UTMPX to UTMP. */
 void
-getutmp (const struct utmpx *utmpx, struct utmp *utmp)
+__getutmp (const struct utmpx *utmpx, struct utmp *utmp)
 {
+  memset (utmp, 0, sizeof (struct utmpx));
   utmp->ut_type = utmpx->ut_type;
   utmp->ut_pid = utmpx->ut_pid;
   memcpy (utmp->ut_line, utmpx->ut_line, sizeof (utmp->ut_line));
   memcpy (utmp->ut_user, utmpx->ut_user, sizeof (utmp->ut_user));
   memcpy (utmp->ut_id, utmpx->ut_id, sizeof (utmp->ut_id));
   memcpy (utmp->ut_host, utmpx->ut_host, sizeof (utmp->ut_host));
-  utmp->ut_tv = utmpx->ut_tv;
+  utmp->ut_tv.tv_sec = utmpx->ut_tv.tv_sec;
+  utmp->ut_tv.tv_usec = utmpx->ut_tv.tv_usec;
 }
+
+weak_alias (__getutmp, getutmp)
+strong_alias (__getutmp, getutmpx)
diff --git a/login/getutmpx.c b/login/getutmpx.c
index 250a355235..839eb6826e 100644
--- a/login/getutmpx.c
+++ b/login/getutmpx.c
@@ -1,34 +1 @@
-/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <string.h>
-#include <utmp.h>
-#include <utmpx.h>
-
-/* Copy the information in UTMP to UTMPX. */
-void
-getutmpx (const struct utmp *utmp, struct utmpx *utmpx)
-{
-  memset (utmpx, 0, sizeof (struct utmpx));
-  utmpx->ut_type = utmp->ut_type;
-  utmpx->ut_pid = utmp->ut_pid;
-  memcpy (utmpx->ut_line, utmp->ut_line, sizeof (utmp->ut_line));
-  memcpy (utmpx->ut_user, utmp->ut_user, sizeof (utmp->ut_user));
-  memcpy (utmpx->ut_id, utmp->ut_id, sizeof (utmp->ut_id));
-  memcpy (utmpx->ut_host, utmp->ut_host, sizeof (utmp->ut_host));
-  utmpx->ut_tv = utmp->ut_tv;
-}
+/* Implemented by getutmp.c. */
diff --git a/login/updwtmp.c b/login/updwtmp.c
index f6cd515ac4..489c28b553 100644
--- a/login/updwtmp.c
+++ b/login/updwtmp.c
@@ -17,11 +17,20 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <utmp.h>
+#include <string.h>
+#include <unistd.h>
 
 #include "utmp-private.h"
 
 #ifndef TRANSFORM_UTMP_FILE_NAME
-# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name)
+# define TRANSFORM_UTMP_FILE_NAME(file_name)	\
+  ((strcmp (file_name, _PATH_UTMP "x") == 0	\
+    && __access (_PATH_UTMP "x", F_OK) != 0)	\
+   ? _PATH_UTMP					\
+   : ((strcmp (file_name, _PATH_WTMP "x") == 0	\
+       && __access (_PATH_WTMP "x", F_OK) != 0)	\
+      ? _PATH_WTMP				\
+      : file_name))
 #endif
 
 void
diff --git a/sysdeps/gnu/utmpx.h b/login/utmpx.h
similarity index 100%
rename from sysdeps/gnu/utmpx.h
rename to login/utmpx.h
diff --git a/sysdeps/gnu/getutmp.c b/sysdeps/gnu/getutmp.c
deleted file mode 100644
index 95a9a4b354..0000000000
--- a/sysdeps/gnu/getutmp.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <assert.h>
-#include <string.h>
-#include <utmp.h>
-#ifndef _UTMPX_H
-/* This is an ugly hack but we must not see the getutmpx declaration.  */
-# define getutmpx XXXgetutmpx
-# include <utmpx.h>
-# undef getutmpx
-#endif
-
-void
-getutmp (const struct utmpx *utmpx, struct utmp *utmp)
-{
-  assert (sizeof (struct utmp) == sizeof (struct utmpx));
-  memcpy (utmp, utmpx, sizeof (struct utmp));
-}
-strong_alias (getutmp, getutmpx)
diff --git a/sysdeps/gnu/getutmpx.c b/sysdeps/gnu/getutmpx.c
deleted file mode 100644
index f393734a63..0000000000
--- a/sysdeps/gnu/getutmpx.c
+++ /dev/null
@@ -1 +0,0 @@
-/* We don't need a separate version.  it is the same as getutmp().  */
diff --git a/sysdeps/gnu/updwtmp.c b/sysdeps/gnu/updwtmp.c
deleted file mode 100644
index 044091b77c..0000000000
--- a/sysdeps/gnu/updwtmp.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (C) 1998-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <string.h>
-#include <unistd.h>
-
-#define TRANSFORM_UTMP_FILE_NAME(file_name)	\
-  ((strcmp (file_name, _PATH_UTMP "x") == 0	\
-    && __access (_PATH_UTMP "x", F_OK) != 0)	\
-   ? _PATH_UTMP					\
-   : ((strcmp (file_name, _PATH_WTMP "x") == 0	\
-       && __access (_PATH_WTMP "x", F_OK) != 0)	\
-      ? _PATH_WTMP				\
-      : file_name))
-
-#include <login/updwtmp.c>
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutmp.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutmp.c
index 6380ae2a82..50ce8c4f5c 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutmp.c
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/getutmp.c
@@ -16,22 +16,15 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <string.h>
-#include <utmp.h>
-/* This is an ugly hack but we must not see the getutmpx declaration.  */
-#define getutmpx XXXgetutmpx
-#include <utmpx.h>
-#undef getutmpx
+#undef weak_alias
+#define weak_alias(a, b)
+#undef strong_alias
+#define strong_alias(a, b)
 
-#include "utmp-compat.h"
+#include <login/getutmp.c>
 
-#undef weak_alias
-#define weak_alias(n,a)
-#define getutmp __getutmp
-#define getutmpx __getutmpx
-#include "sysdeps/gnu/getutmp.c"
-#undef getutmp
-#undef getutmpx
+#include "utmp-compat.h"
 
 default_symbol_version (__getutmp, getutmp, UTMP_COMPAT_BASE);
+_strong_alias (__getutmp, __getutmpx)
 default_symbol_version (__getutmpx, getutmpx, UTMP_COMPAT_BASE);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/updwtmp.c b/sysdeps/unix/sysv/linux/s390/s390-32/updwtmp.c
index dcd334e5a9..2079571cc1 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/updwtmp.c
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/updwtmp.c
@@ -25,7 +25,7 @@
 # undef weak_alias
 # define weak_alias(n,a)
 #endif
-#include "sysdeps/gnu/updwtmp.c"
+#include <login/updwtmp.c>
 
 #if defined SHARED
 default_symbol_version (__updwtmp, updwtmp, UTMP_COMPAT_BASE);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 2/7] Consolidate and simplify internal utmp definitions
  2020-08-05 18:59 [PATCH v2 1/7] login: Move gnu utmpx to default implementation Adhemerval Zanella via Libc-alpha
@ 2020-08-05 18:59 ` Adhemerval Zanella via Libc-alpha
  2020-08-05 18:59 ` [PATCH v2 3/7] support: Add 'touch' command Adhemerval Zanella via Libc-alpha
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 18:59 UTC (permalink / raw)
  To: libc-alpha

The TRANSFORM_UTMP_FILE_NAME macro is moved to the inline function
utmp_file_name_time32 at utmp-path.h and the __utmp_equal function
is removed and inlined on its only usage  (matches_last_entry at
utmp_file.c).

Checked with make check run-built-tests=no on all afftected ABIs.
---
 login/updwtmp.c                              | 14 +----
 sysdeps/gnu/utmp_file.c => login/utmp-path.h | 32 ++++++++----
 login/utmp_file.c                            | 26 ++++++---
 manual/users.texi                            |  4 +-
 sysdeps/generic/paths.h                      |  8 +--
 sysdeps/generic/utmp-equal.h                 | 42 ---------------
 sysdeps/unix/sysv/linux/paths.h              |  6 ++-
 sysdeps/unix/sysv/linux/updwtmp.c            | 37 -------------
 sysdeps/unix/sysv/linux/utmp-path.h          | 55 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/utmp_file.c          | 37 -------------
 10 files changed, 107 insertions(+), 154 deletions(-)
 rename sysdeps/gnu/utmp_file.c => login/utmp-path.h (50%)
 delete mode 100644 sysdeps/generic/utmp-equal.h
 delete mode 100644 sysdeps/unix/sysv/linux/updwtmp.c
 create mode 100644 sysdeps/unix/sysv/linux/utmp-path.h
 delete mode 100644 sysdeps/unix/sysv/linux/utmp_file.c

diff --git a/login/updwtmp.c b/login/updwtmp.c
index 489c28b553..42a2152b60 100644
--- a/login/updwtmp.c
+++ b/login/updwtmp.c
@@ -21,22 +21,12 @@
 #include <unistd.h>
 
 #include "utmp-private.h"
-
-#ifndef TRANSFORM_UTMP_FILE_NAME
-# define TRANSFORM_UTMP_FILE_NAME(file_name)	\
-  ((strcmp (file_name, _PATH_UTMP "x") == 0	\
-    && __access (_PATH_UTMP "x", F_OK) != 0)	\
-   ? _PATH_UTMP					\
-   : ((strcmp (file_name, _PATH_WTMP "x") == 0	\
-       && __access (_PATH_WTMP "x", F_OK) != 0)	\
-      ? _PATH_WTMP				\
-      : file_name))
-#endif
+#include <utmp-path.h>
 
 void
 __updwtmp (const char *wtmp_file, const struct utmp *utmp)
 {
-  const char *file_name = TRANSFORM_UTMP_FILE_NAME (wtmp_file);
+  const char *file_name = utmp_file_name_time32 (wtmp_file);
 
   __libc_updwtmp (file_name, utmp);
 }
diff --git a/sysdeps/gnu/utmp_file.c b/login/utmp-path.h
similarity index 50%
rename from sysdeps/gnu/utmp_file.c
rename to login/utmp-path.h
index 25ceaa897c..c284c8c398 100644
--- a/sysdeps/gnu/utmp_file.c
+++ b/login/utmp-path.h
@@ -1,6 +1,6 @@
-/* Copyright (C) 1998-2020 Free Software Foundation, Inc.
+/* Handle {u,w}tmp and {u,w}tmpx file name usage.
+   Copyright (C) 1998-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -16,16 +16,26 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#ifndef _UTMP_PATH_H
+#define _UTMP_PATH_H 1
+
 #include <string.h>
 #include <unistd.h>
 
-#define TRANSFORM_UTMP_FILE_NAME(file_name)	\
-  ((strcmp (file_name, _PATH_UTMP "x") == 0	\
-    && __access (_PATH_UTMP "x", F_OK) != 0)	\
-   ? _PATH_UTMP					\
-   : ((strcmp (file_name, _PATH_WTMP "x") == 0	\
-       && __access (_PATH_WTMP "x", F_OK) != 0)	\
-      ? _PATH_WTMP				\
-      : file_name))
+/* The function returns the utmp database for 32-bit utmp{x} entries based
+   on FILE_NAME.  If the argument ends with 'x' and the file does not
+   exits the default old utmp{x} name is returned instead.  */
+static inline const char *
+utmp_file_name_time32 (const char *file_name)
+{
+  if (strcmp (file_name, _PATH_UTMP_BASE "x") == 0
+      && __access (_PATH_UTMP_BASE "x", F_OK) != 0)
+    return _PATH_UTMP_BASE;
+  else if (strcmp (file_name, _PATH_WTMP_BASE "x") == 0
+	   && __access (_PATH_WTMP_BASE "x", F_OK) != 0)
+    return _PATH_UTMP_BASE;
+
+  return file_name;
+}
 
-#include <login/utmp_file.c>
+#endif /* _UTMP_PATH_H  */
diff --git a/login/utmp_file.c b/login/utmp_file.c
index f095139c51..4f4f0cf4e4 100644
--- a/login/utmp_file.c
+++ b/login/utmp_file.c
@@ -32,7 +32,7 @@
 #include <not-cancel.h>
 
 #include "utmp-private.h"
-#include "utmp-equal.h"
+#include <utmp-path.h>
 
 
 /* Descriptor for the file and position.  */
@@ -60,7 +60,21 @@ matches_last_entry (const struct utmp *data)
     return data->ut_type == last_entry.ut_type;
   else
     /* For the process-related entries, a full match is needed.  */
-    return __utmp_equal (&last_entry, data);
+    return (data->ut_type == INIT_PROCESS
+	    || data->ut_type == LOGIN_PROCESS
+	    || data->ut_type == USER_PROCESS
+	    || data->ut_type == DEAD_PROCESS)
+      && (last_entry.ut_type == INIT_PROCESS
+	  || last_entry.ut_type == LOGIN_PROCESS
+	  || last_entry.ut_type == USER_PROCESS
+	  || last_entry.ut_type == DEAD_PROCESS)
+      && (data->ut_id[0] && last_entry.ut_id[0]
+	  ? strncmp (data->ut_id, last_entry.ut_id,
+		     sizeof last_entry.ut_id)
+	    == 0
+	  : (strncmp (data->ut_line, last_entry.ut_line,
+		      sizeof last_entry.ut_line)
+	     == 0));
 }
 
 /* Locking timeout.  */
@@ -129,10 +143,6 @@ file_unlock (int fd)
   __fcntl64_nocancel (fd, F_SETLKW, &fl);
 }
 
-#ifndef TRANSFORM_UTMP_FILE_NAME
-# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name)
-#endif
-
 int
 __libc_setutent (void)
 {
@@ -140,7 +150,7 @@ __libc_setutent (void)
     {
       const char *file_name;
 
-      file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name);
+      file_name = utmp_file_name_time32 (__libc_utmp_file_name);
 
       file_writable = false;
       file_fd = __open_nocancel
@@ -353,7 +363,7 @@ __libc_pututline (const struct utmp *data)
   if (! file_writable)
     {
       /* We must make the file descriptor writable before going on.  */
-      const char *file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name);
+      const char *file_name = utmp_file_name_time32 (__libc_utmp_file_name);
 
       int new_fd = __open_nocancel
 	(file_name, O_RDWR | O_LARGEFILE | O_CLOEXEC);
diff --git a/manual/users.texi b/manual/users.texi
index ec22ce6c1c..dcaca1dcf1 100644
--- a/manual/users.texi
+++ b/manual/users.texi
@@ -1234,7 +1234,7 @@ over again.
 @c   pututline_unknown @mtasurace:utent @acsfd
 @c    setutent_unknown dup @mtasurace:utent @acsfd
 @c   pututline_file @mtascusig:ALRM @mtascutimer @acsfd
-@c    TRANSFORM_UTMP_FILE_NAME ok
+@c    utmp_file_name_time32 ok
 @c     strcmp dup ok
 @c     acesss dup ok
 @c    open_not_cancel_2 dup @acsfd
@@ -1427,7 +1427,7 @@ the following function:
 @standards{SVID, utmp.h}
 @safety{@prelim{}@mtunsafe{@mtascusig{:ALRM} @mtascutimer{}}@asunsafe{}@acunsafe{@acsfd{}}}
 @c updwtmp @mtascusig:ALRM @mtascutimer @acsfd
-@c  TRANSFORM_UTMP_FILE_NAME dup ok
+@c  utmp_file_name_time32 dup ok
 @c  *libc_utmp_file_functions->updwtmp = updwtmp_file @mtascusig:ALRM @mtascutimer @acsfd
 @c   open_not_cancel_2 dup @acsfd
 @c   LOCK_FILE dup @mtascusig:ALRM @mtascutimer
diff --git a/sysdeps/generic/paths.h b/sysdeps/generic/paths.h
index 893b4c2286..99a791ce31 100644
--- a/sysdeps/generic/paths.h
+++ b/sysdeps/generic/paths.h
@@ -60,10 +60,12 @@
 #define	_PATH_SHELLS	"/etc/shells"
 #define	_PATH_TTY	"/dev/tty"
 #define	_PATH_UNIX	"/vmunix"
-#define	_PATH_UTMP	"/var/run/utmp"
-#define	_PATH_UTMP_DB	"/var/run/utmp.db"
+#define	_PATH_UTMP_BASE	"/var/run/utmp"
+#define	_PATH_UTMP	_PATH_UTMP_BASE
+#define	_PATH_UTMP_DB	_PATH_UTMP_BASE ".db"
 #define	_PATH_VI	"/usr/bin/vi"
-#define	_PATH_WTMP	"/var/log/wtmp"
+#define	_PATH_WTMP_BASE	"/var/log/wtmp"
+#define	_PATH_WTMP	_PATH_WTMP_BASE
 
 /* Provide trailing slash, since mostly used for building pathnames. */
 #define	_PATH_DEV	"/dev/"
diff --git a/sysdeps/generic/utmp-equal.h b/sysdeps/generic/utmp-equal.h
deleted file mode 100644
index cd0e3e79a0..0000000000
--- a/sysdeps/generic/utmp-equal.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Helper function for utmp functions to see if two entries are equal.
-   Copyright (C) 1996-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>
-   and Paul Janzen <pcj@primenet.com>, 1996.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <string.h>
-#include <utmp.h>
-
-#include "utmp-private.h"
-
-/* Test whether two entries match.  */
-static int
-__utmp_equal (const struct utmp *entry, const struct utmp *match)
-{
-  return (entry->ut_type == INIT_PROCESS
-          || entry->ut_type == LOGIN_PROCESS
-          || entry->ut_type == USER_PROCESS
-          || entry->ut_type == DEAD_PROCESS)
-    && (match->ut_type == INIT_PROCESS
-        || match->ut_type == LOGIN_PROCESS
-        || match->ut_type == USER_PROCESS
-        || match->ut_type == DEAD_PROCESS)
-    && (entry->ut_id[0] && match->ut_id[0]
-        ? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0
-        : (strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line)
-           == 0));
-}
diff --git a/sysdeps/unix/sysv/linux/paths.h b/sysdeps/unix/sysv/linux/paths.h
index 1342ab3a96..3b8aeab788 100644
--- a/sysdeps/unix/sysv/linux/paths.h
+++ b/sysdeps/unix/sysv/linux/paths.h
@@ -61,9 +61,11 @@
 #define	_PATH_SHELLS	"/etc/shells"
 #define	_PATH_TTY	"/dev/tty"
 #define	_PATH_UNIX	"/boot/vmlinux"
-#define	_PATH_UTMP	"/var/run/utmp"
+#define	_PATH_UTMP_BASE	"/var/run/utmp"
+#define	_PATH_UTMP	_PATH_UTMP_BASE
 #define	_PATH_VI	"/usr/bin/vi"
-#define	_PATH_WTMP	"/var/log/wtmp"
+#define	_PATH_WTMP_BASE	"/var/log/wtmp"
+#define	_PATH_WTMP	_PATH_WTMP_BASE
 
 /* Provide trailing slash, since mostly used for building pathnames. */
 #define	_PATH_DEV	"/dev/"
diff --git a/sysdeps/unix/sysv/linux/updwtmp.c b/sysdeps/unix/sysv/linux/updwtmp.c
deleted file mode 100644
index 333317bfe2..0000000000
--- a/sysdeps/unix/sysv/linux/updwtmp.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (C) 1998-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <string.h>
-#include <unistd.h>
-
-#define TRANSFORM_UTMP_FILE_NAME(file_name)		\
-  ((strcmp (file_name, _PATH_UTMP) == 0			\
-    && __access (_PATH_UTMP "x", F_OK) == 0)		\
-   ? (_PATH_UTMP "x")					\
-   : ((strcmp (file_name, _PATH_WTMP) == 0		\
-       && __access ( _PATH_WTMP "x", F_OK) == 0)	\
-      ? (_PATH_WTMP "x")				\
-      : ((strcmp (file_name, _PATH_UTMP "x") == 0	\
-	  && __access (_PATH_UTMP "x", F_OK) != 0)	\
-	 ? _PATH_UTMP					\
-	 : ((strcmp (file_name, _PATH_WTMP "x") == 0	\
-	     && __access (_PATH_WTMP "x", F_OK) != 0)	\
-	    ? _PATH_WTMP				\
-	    : file_name))))
-
-#include <login/updwtmp.c>
diff --git a/sysdeps/unix/sysv/linux/utmp-path.h b/sysdeps/unix/sysv/linux/utmp-path.h
new file mode 100644
index 0000000000..a377bc9dba
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/utmp-path.h
@@ -0,0 +1,55 @@
+/* Handle {u,w}tmp and {u,w}tmpx file name usage.
+   Copyright (C) 1998-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _UTMP_PATH_H
+#define _UTMP_PATH_H 1
+
+#include <string.h>
+#include <unistd.h>
+
+
+/* The function returns the utmp database for 32-bit utmp{x} entries based
+   on FILE_NAME:
+
+   - if the default {x,w}utmp name is used but a file name ending with 'x'
+     exists it is returned instead
+
+   - if the argument ends with 'x' and the file is not accessible the default
+     {x,w}utmp is returned instead.
+
+   - if neither 1. nor 2. applies, the FILE_NAME is returned instead.  */
+static inline const char *
+utmp_file_name_time32 (const char *file_name)
+{
+  if (strcmp (file_name, _PATH_UTMP_BASE) == 0
+      && __access (_PATH_UTMP_BASE "x", F_OK) == 0)
+    return _PATH_UTMP_BASE "x";
+  else if (strcmp (file_name, _PATH_WTMP_BASE) == 0
+           && __access (_PATH_WTMP_BASE "x", F_OK) == 0)
+    return _PATH_WTMP_BASE "x";
+  else if (strcmp (file_name, _PATH_UTMP_BASE "x") == 0
+           && __access (_PATH_UTMP_BASE "x", F_OK) != 0)
+    return _PATH_UTMP_BASE;
+  else if (strcmp (file_name, _PATH_WTMP_BASE "x") == 0
+           && __access (_PATH_WTMP_BASE "x", F_OK) != 0)
+    return _PATH_WTMP_BASE;
+
+  return file_name;
+}
+
+#endif /* _UTMP_PATH_H  */
diff --git a/sysdeps/unix/sysv/linux/utmp_file.c b/sysdeps/unix/sysv/linux/utmp_file.c
deleted file mode 100644
index 71da027a5f..0000000000
--- a/sysdeps/unix/sysv/linux/utmp_file.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (C) 1998-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <string.h>
-#include <unistd.h>
-
-#define TRANSFORM_UTMP_FILE_NAME(file_name)		\
-  ((strcmp (file_name, _PATH_UTMP) == 0			\
-    && __access (_PATH_UTMP "x", F_OK) == 0)		\
-   ? (_PATH_UTMP "x")					\
-   : ((strcmp (file_name, _PATH_WTMP) == 0		\
-       && __access ( _PATH_WTMP "x", F_OK) == 0)	\
-      ? (_PATH_WTMP "x")				\
-      : ((strcmp (file_name, _PATH_UTMP "x") == 0	\
-	  && __access (_PATH_UTMP "x", F_OK) != 0)	\
-	 ? _PATH_UTMP					\
-	 : ((strcmp (file_name, _PATH_WTMP "x") == 0	\
-	     && __access (_PATH_WTMP "x", F_OK) != 0)	\
-	    ? _PATH_WTMP				\
-	    : file_name))))
-
-#include <login/utmp_file.c>
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 3/7] support: Add 'touch' command
  2020-08-05 18:59 [PATCH v2 1/7] login: Move gnu utmpx to default implementation Adhemerval Zanella via Libc-alpha
  2020-08-05 18:59 ` [PATCH v2 2/7] Consolidate and simplify internal utmp definitions Adhemerval Zanella via Libc-alpha
@ 2020-08-05 18:59 ` Adhemerval Zanella via Libc-alpha
  2020-08-05 19:08   ` DJ Delorie via Libc-alpha
  2020-08-05 18:59 ` [PATCH v2 4/7] login: Add 64-bit time support to utmp/utmpx Adhemerval Zanella via Libc-alpha
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 18:59 UTC (permalink / raw)
  To: libc-alpha

It allow creates empty files with an specific mode.
---
 support/test-container.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/support/test-container.c b/support/test-container.c
index e9109f9e3d..b6101b9b94 100644
--- a/support/test-container.c
+++ b/support/test-container.c
@@ -102,6 +102,7 @@ int verbose = 0;
 	 cwd PATH
 	 exec FILE
 	 mkdirp MODE DIR
+	 touch MODE FILE
 
        variables:
 	 $B/ build dir, equivalent to $(common-objpfx)
@@ -127,6 +128,7 @@ int verbose = 0;
 	 - 'cwd': set test working directory
 	 - 'exec': change test binary location (may end in /)
 	 - 'mkdirp': A minimal "mkdir -p FILE" command.
+	 - 'touch': A minimal 'touch' command to create empty files.
 
    * mytest.root/postclean.req causes fresh rsync (with delete) after
      test if present
@@ -999,6 +1001,15 @@ main (int argc, char **argv)
 		TEST_COMPARE (errno, 0);
 		xmkdirp (the_words[2], m);
 	      }
+	    else if (nt == 3 && strcmp (the_words[0], "touch") == 0)
+	      {
+		long int m;
+		errno = 0;
+		m = strtol (the_words[1], NULL, 0);
+		TEST_COMPARE (errno, 0);
+
+		xopen (the_words[2], O_WRONLY | O_TRUNC | O_CREAT, m);
+	      }
 	    else if (nt > 0 && the_words[0][0] != '#')
 	      {
 		fprintf (stderr, "\033[31minvalid [%s]\033[0m\n", the_words[0]);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 4/7] login: Add 64-bit time support to utmp/utmpx
  2020-08-05 18:59 [PATCH v2 1/7] login: Move gnu utmpx to default implementation Adhemerval Zanella via Libc-alpha
  2020-08-05 18:59 ` [PATCH v2 2/7] Consolidate and simplify internal utmp definitions Adhemerval Zanella via Libc-alpha
  2020-08-05 18:59 ` [PATCH v2 3/7] support: Add 'touch' command Adhemerval Zanella via Libc-alpha
@ 2020-08-05 18:59 ` Adhemerval Zanella via Libc-alpha
  2020-08-05 19:28   ` Joseph Myers
  2020-08-05 18:59 ` [PATCH v2 5/7] linux: Add pwrite64_nocancel Adhemerval Zanella via Libc-alpha
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 18:59 UTC (permalink / raw)
  To: libc-alpha

The new struct has the same size of 32-bit and 64-bit architecture with
two main differences compared to the 32-bit time_t one:

  1. ut_session is now 64-bit and it is mainly to set the ut_tv member
     alignment to be similar on both 32-bit and 64-bit architecture
     (for architectures that support multiple ABIs with different
     wordsize, such as x86).

  2. The internal tv_sec and tv_usec for ut_tv are now 64-bit.  Although
     it does not fully fix BZ#17470 not BZ#18235, it might allow define
     the type as 'struct timeval' for __TIMESIZE=64 (thus fixing the
     aforementioned bug in this build configuration).

Different than laid out on the Y2038 Proofness Design [1], the
'utmp.trans' strategy is not used.  Instead:

  - New file names are defined for _PATH_UTMP, _PATH_WTMP, and
    _PATH_UTMP_DB (if applicable) and used as default for the new 2.33
    utmp{x} symbols.

  - The new utmp{x} symbols read/write 64-bit time_t entries as default.
    However if the old _PATH_UTMP or _PATH_WTMP is passed on
    utm{x}pname or updwtmp, the implementation read 32-bit utmp{x}
    entries and convert it to 64-bit ones.

  - The compat symbols read/write 32-bit time_t entries as default.
    If the default _PATH_UTMP or _PATH_WTMP is passed on
    utm{x}pname or updwtmp, the implementation reads 64-bit entries
    and convert to 32-bit ones.

The idea is not to maintain multiple databases with different formats
(which has underlying issues due to complexity, how to handle register
that might overflow, and increases the security surface of BZ#24492),
but rather to move new application to use y2038 ones due the inherent
issue of 32-bit time database (which affects 64-bit architecture as
well, modulo s390).

If required the system might provide a tool to convert the old format
to newer one by opening the old file with utmpname and copying the
entries to the new format with updwtmp.

Also, for new 64-bit databases the path is not redirected to use the
utmpx one depending of the file existance (utmp_file_name_time32).
This is undocumented behavior most likely added be compatible with
Solaris (which defines different utmp dabases for utmpx files).

The s390 is an outlier, the 31-bit ABI added 64-bit time support on
GLIBC 2.8 and 64-bit has support since its inclusion.  The s390 ABI
follows the above design, but with a different ABI base version
(2.8 vs 2.33). The s390x instead does not have support to read/write
32-bit registers and does not provide compat symbols.

Checked on x86_64-linux-gnu and i686-linux-gnu.

[1] https://sourceware.org/glibc/wiki/Y2038ProofnessDesign#utmp_types_and_APIs
---
 bits/types/struct_utmp.h                      |  12 +-
 bits/types/struct_utmpx.h                     |  11 +-
 include/utmp.h                                |   5 +-
 login/Makefile                                |   7 +-
 login/Versions                                |   7 +
 login/getutent.c                              |   7 +-
 login/getutent_r.c                            |  48 +-
 login/getutid.c                               |   7 +-
 login/getutid_r.c                             |  33 +-
 login/getutline.c                             |   7 +-
 login/getutline_r.c                           |  33 +-
 login/getutmp.c                               |  10 +-
 login/getutxent.c                             |   9 +-
 login/getutxid.c                              |   9 +-
 login/getutxline.c                            |   9 +-
 login/login.c                                 |  10 +-
 .../linux/s390/s390-32 => login}/login32.c    |  16 +-
 login/pututxline.c                            |   9 +-
 login/tst-utmp-default.c                      | 292 ++++++++++++
 .../tst-utmp-default.script                   |  10 +
 login/tst-utmp32.c                            | 325 +++++++++++++
 login/tst-utmp32.root/tst-utmp32.script       |   7 +
 login/updwtmp.c                               |  25 +-
 login/updwtmpx.c                              |   9 +-
 .../utmp-convert.h => login/utmp-convert.c    |  59 +--
 .../getutent.c => login/utmp-convert.h        |  28 +-
 login/utmp-path.h                             |   2 +-
 login/utmp-private.h                          |  22 +-
 login/utmp32.c                                | 245 ++++++++++
 .../linux/s390/s390-32 => login}/utmp32.h     |   9 +
 login/utmp_file.c                             | 439 +++++++++++-------
 login/utmpname.c                              |  10 +
 login/utmpx32.c                               | 111 +++++
 .../linux/s390/s390-32 => login}/utmpx32.h    |   6 +-
 sysdeps/generic/paths.h                       |   7 +-
 sysdeps/generic/utmp-compat.h                 |   3 +
 sysdeps/mach/hurd/i386/libc.abilist           |  15 +
 sysdeps/mach/hurd/i386/libutil.abilist        |   1 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |  15 +
 .../unix/sysv/linux/aarch64/libutil.abilist   |   1 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |  15 +
 sysdeps/unix/sysv/linux/alpha/libutil.abilist |   1 +
 sysdeps/unix/sysv/linux/arc/libc.abilist      |  15 +
 sysdeps/unix/sysv/linux/arc/libutil.abilist   |   1 +
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |  15 +
 .../unix/sysv/linux/arm/le/libutil.abilist    |   1 +
 sysdeps/unix/sysv/linux/csky/libc.abilist     |  15 +
 sysdeps/unix/sysv/linux/csky/libutil.abilist  |   1 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |  15 +
 sysdeps/unix/sysv/linux/hppa/libutil.abilist  |   1 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |  15 +
 sysdeps/unix/sysv/linux/i386/libutil.abilist  |   1 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |  15 +
 sysdeps/unix/sysv/linux/ia64/libutil.abilist  |   1 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |  15 +
 .../sysv/linux/m68k/m680x0/libutil.abilist    |   1 +
 .../sysv/linux/microblaze/be/libc.abilist     |  15 +
 .../sysv/linux/microblaze/be/libutil.abilist  |   1 +
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |  15 +
 .../sysv/linux/mips/mips32/libutil.abilist    |   1 +
 .../sysv/linux/mips/mips64/libutil.abilist    |   1 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |  15 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |  15 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |  15 +
 sysdeps/unix/sysv/linux/nios2/libutil.abilist |   1 +
 sysdeps/unix/sysv/linux/paths.h               |   5 +-
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |  15 +
 .../linux/powerpc/powerpc32/libutil.abilist   |   1 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |  15 +
 .../powerpc/powerpc64/be/libutil.abilist      |   1 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |  15 +
 .../powerpc/powerpc64/le/libutil.abilist      |   1 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |  15 +
 .../sysv/linux/riscv/rv64/libutil.abilist     |   1 +
 .../unix/sysv/linux/s390/s390-32/getutent_r.c |  38 --
 .../unix/sysv/linux/s390/s390-32/getutid.c    |  32 --
 .../unix/sysv/linux/s390/s390-32/getutid_r.c  |  35 --
 .../unix/sysv/linux/s390/s390-32/getutline.c  |  32 --
 .../sysv/linux/s390/s390-32/getutline_r.c     |  34 --
 .../unix/sysv/linux/s390/s390-32/getutmp.c    |  30 --
 .../unix/sysv/linux/s390/s390-32/getutxent.c  |  30 --
 .../unix/sysv/linux/s390/s390-32/getutxid.c   |  30 --
 .../unix/sysv/linux/s390/s390-32/getutxline.c |  30 --
 sysdeps/unix/sysv/linux/s390/s390-32/login.c  |  35 --
 .../unix/sysv/linux/s390/s390-32/pututxline.c |  30 --
 .../unix/sysv/linux/s390/s390-32/updwtmp.c    |  32 --
 .../unix/sysv/linux/s390/s390-32/updwtmpx.c   |  30 --
 .../sysv/linux/s390/s390-32/utmp-compat.h     |   2 +-
 sysdeps/unix/sysv/linux/s390/s390-32/utmp32.c | 184 --------
 .../sysv/linux/s390/s390-32/utmpx-convert.h   |  85 ----
 .../unix/sysv/linux/s390/s390-32/utmpx32.c    | 139 ------
 .../sysv/linux/s390/s390-64/utmp-compat.h     |   3 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |  15 +
 sysdeps/unix/sysv/linux/sh/le/libutil.abilist |   1 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |  15 +
 .../sysv/linux/sparc/sparc32/libutil.abilist  |   1 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |  15 +
 .../sysv/linux/sparc/sparc64/libutil.abilist  |   1 +
 sysdeps/unix/sysv/linux/utmp-path.h           |   3 +-
 .../unix/sysv/linux/x86_64/64/libc.abilist    |  15 +
 .../unix/sysv/linux/x86_64/64/libutil.abilist |   1 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |  15 +
 .../sysv/linux/x86_64/x32/libutil.abilist     |   1 +
 103 files changed, 1970 insertions(+), 1110 deletions(-)
 rename {sysdeps/unix/sysv/linux/s390/s390-32 => login}/login32.c (72%)
 create mode 100644 login/tst-utmp-default.c
 create mode 100644 login/tst-utmp-default.root/tst-utmp-default.script
 create mode 100644 login/tst-utmp32.c
 create mode 100644 login/tst-utmp32.root/tst-utmp32.script
 rename sysdeps/unix/sysv/linux/s390/s390-32/utmp-convert.h => login/utmp-convert.c (58%)
 rename sysdeps/unix/sysv/linux/s390/s390-32/getutent.c => login/utmp-convert.h (59%)
 create mode 100644 login/utmp32.c
 rename {sysdeps/unix/sysv/linux/s390/s390-32 => login}/utmp32.h (78%)
 create mode 100644 login/utmpx32.c
 rename {sysdeps/unix/sysv/linux/s390/s390-32 => login}/utmpx32.h (93%)
 create mode 100644 sysdeps/generic/utmp-compat.h
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getutent_r.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getutid.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getutid_r.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getutline.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getutline_r.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getutmp.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getutxent.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getutxid.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/getutxline.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/login.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/pututxline.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/updwtmp.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/updwtmpx.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/utmp32.c
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/utmpx-convert.h
 delete mode 100644 sysdeps/unix/sysv/linux/s390/s390-32/utmpx32.c
 create mode 100644 sysdeps/unix/sysv/linux/s390/s390-64/utmp-compat.h

diff --git a/bits/types/struct_utmp.h b/bits/types/struct_utmp.h
index 4b05c91515..19b9bca1e7 100644
--- a/bits/types/struct_utmp.h
+++ b/bits/types/struct_utmp.h
@@ -38,18 +38,16 @@ struct utmp
 /* The ut_session and ut_tv fields must be the same size when compiled
    32- and 64-bit.  This allows data files and shared memory to be
    shared between 32- and 64-bit applications.  */
-#if __WORDSIZE_TIME64_COMPAT32
-  int32_t ut_session;		/* Session ID, used for windowing.  */
+  int64_t ut_session;		/* Session ID, used for windowing.  */
+#if __TIMESIZE != 64
   struct
   {
-    int32_t tv_sec;		/* Seconds.  */
-    int32_t tv_usec;		/* Microseconds.  */
+    int64_t tv_sec;		/* Seconds.  */
+    int64_t tv_usec;		/* Microseconds.  */
   } ut_tv;			/* Time entry was made.  */
 #else
-  long int ut_session;		/* Session ID, used for windowing.  */
   struct timeval ut_tv;		/* Time entry was made.  */
 #endif
-
   int32_t ut_addr_v6[4];	/* Internet address of remote host.  */
-  char __glibc_reserved[20];		/* Reserved for future use.  */
+  char __glibc_reserved[8];	/* Reserved for future use.  */
 };
diff --git a/bits/types/struct_utmpx.h b/bits/types/struct_utmpx.h
index 8bfc786cd8..27ef28e70f 100644
--- a/bits/types/struct_utmpx.h
+++ b/bits/types/struct_utmpx.h
@@ -39,17 +39,16 @@ struct utmpx
 /* The fields ut_session and ut_tv must be the same size when compiled
    32- and 64-bit.  This allows files and shared memory to be shared
    between 32- and 64-bit applications.  */
-#if __WORDSIZE_TIME64_COMPAT32
-  __int32_t ut_session;		/* Session ID, used for windowing.  */
+  __int64_t ut_session;		/* Session ID, used for windowing.  */
+#if __TIMESIZE != 64
   struct
   {
-    __int32_t tv_sec;		/* Seconds.  */
-    __int32_t tv_usec;		/* Microseconds.  */
+    __int64_t tv_sec;		/* Seconds.  */
+    __int64_t tv_usec;		/* Microseconds.  */
   } ut_tv;			/* Time entry was made.  */
 #else
-  long int ut_session;		/* Session ID, used for windowing.  */
   struct timeval ut_tv;		/* Time entry was made.  */
 #endif
   __int32_t ut_addr_v6[4];	/* Internet address of remote host.  */
-  char __glibc_reserved[20];		/* Reserved for future use.  */
+  char __glibc_reserved[8];	/* Reserved for future use.  */
 };
diff --git a/include/utmp.h b/include/utmp.h
index 374184e9b2..7a205c13e2 100644
--- a/include/utmp.h
+++ b/include/utmp.h
@@ -9,7 +9,7 @@ libc_hidden_proto (__updwtmp)
 extern int __utmpname (const char *__file) attribute_hidden;
 extern struct utmp *__getutent (void);
 libc_hidden_proto (__getutent)
-extern void __setutent (void) attribute_hidden;
+extern void __setutent (void);
 extern void __endutent (void) attribute_hidden;
 extern struct utmp *__getutid (const struct utmp *__id);
 libc_hidden_proto (__getutid)
@@ -26,6 +26,9 @@ extern int __getutline_r (const struct utmp *__line,
 			  struct utmp *__buffer, struct utmp **__result);
 libc_hidden_proto (__getutline_r)
 
+extern void __login (const struct utmp *ut);
+hidden_proto (__login)
+
 libutil_hidden_proto (login_tty)
 
 # endif /* !_ISOMAC */
diff --git a/login/Makefile b/login/Makefile
index c61d1950bb..848caa0c44 100644
--- a/login/Makefile
+++ b/login/Makefile
@@ -31,7 +31,7 @@ headers	:= utmp.h bits/utmp.h lastlog.h pty.h \
 routines := getlogin getlogin_r setlogin getlogin_r_chk \
 	    getutent getutent_r getutid getutline getutid_r getutline_r \
 	    utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname \
-	    ptsname_r_chk
+	    ptsname_r_chk utmp32 utmpx32 utmp-convert
 
 CFLAGS-grantpt.c += -DLIBEXECDIR='"$(libexecdir)"'
 
@@ -49,11 +49,14 @@ vpath %.c programs
 tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
   tst-pututxline-lockfail tst-pututxline-cache
 
+tests-internal := tst-utmp32
+tests-container := tst-utmp32 tst-utmp-default
+
 # Build the -lutil library with these extra functions.
 extra-libs      := libutil
 extra-libs-others := $(extra-libs)
 
-libutil-routines:= login login_tty logout logwtmp openpty forkpty
+libutil-routines:= login login_tty logout logwtmp openpty forkpty login32
 
 include ../Rules
 
diff --git a/login/Versions b/login/Versions
index 475fcf063f..6c53d6639e 100644
--- a/login/Versions
+++ b/login/Versions
@@ -45,10 +45,17 @@ libc {
     __getlogin_r_chk;
     __ptsname_r_chk;
   }
+  GLIBC_PRIVATE {
+    # Used on compat login from libutil.
+    __utmp_convert32to64;
+  }
 }
 
 libutil {
   GLIBC_2.0 {
     forkpty; login; login_tty; logout; logwtmp; openpty;
   }
+  GLIBC_2.33 {
+    login;
+  }
 }
diff --git a/login/getutent.c b/login/getutent.c
index 3a8b78c9be..16ca2622d1 100644
--- a/login/getutent.c
+++ b/login/getutent.c
@@ -18,7 +18,8 @@
 
 #include <stdlib.h>
 #include <utmp.h>
-
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 /* Local buffer to store the result.  */
 libc_freeres_ptr (static struct utmp *buffer);
@@ -42,4 +43,8 @@ __getutent (void)
   return result;
 }
 libc_hidden_def (__getutent)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutent, getutent, UTMP_COMPAT_BASE);
+#else
 weak_alias (__getutent, getutent)
+#endif
diff --git a/login/getutent_r.c b/login/getutent_r.c
index 7bf5fe136a..824b1c7a53 100644
--- a/login/getutent_r.c
+++ b/login/getutent_r.c
@@ -20,8 +20,11 @@
 #include <libc-lock.h>
 #include <stdlib.h>
 #include <utmp.h>
+#include <utmp-compat.h>
+#include <shlib-compat.h>
+#include <utmp-private.h>
+#include <utmp-convert.h>
 
-#include "utmp-private.h"
 
 /* We need to protect the opening of the file.  */
 __libc_lock_define_initialized (, __libc_utmp_lock attribute_hidden)
@@ -32,7 +35,12 @@ __setutent (void)
 {
   __libc_lock_lock (__libc_utmp_lock);
 
-  __libc_setutent ();
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+  if (__libc_utmpname_mode == UTMPNAME_TIME32)
+    __libc_setutent32 ();
+  else
+#endif
+    __libc_setutent ();
 
   __libc_lock_unlock (__libc_utmp_lock);
 }
@@ -46,14 +54,32 @@ __getutent_r (struct utmp *buffer, struct utmp **result)
 
   __libc_lock_lock (__libc_utmp_lock);
 
-  retval = __libc_getutent_r (buffer, result);
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+  if (__libc_utmpname_mode == UTMPNAME_TIME32)
+    {
+      struct utmp32 out32;
+      struct utmp32 *out32p;
+      retval = __libc_getutent32_r (&out32, &out32p);
+      if (retval == 0)
+	{
+	  __utmp_convert32to64 (out32p, buffer);
+	  *result = buffer;
+	}
+    }
+  else
+#endif
+    retval = __libc_getutent_r (buffer, result);
 
   __libc_lock_unlock (__libc_utmp_lock);
 
   return retval;
 }
 libc_hidden_def (__getutent_r)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutent_r, getutent_r, UTMP_COMPAT_BASE);
+#else
 weak_alias (__getutent_r, getutent_r)
+#endif
 
 
 struct utmp *
@@ -63,14 +89,28 @@ __pututline (const struct utmp *data)
 
   __libc_lock_lock (__libc_utmp_lock);
 
-  buffer = __libc_pututline (data);
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+  if (__libc_utmpname_mode == UTMPNAME_TIME32)
+    {
+      struct utmp32 in32;
+      __utmp_convert64to32 (data, &in32);
+      struct utmp32 *out32p = __libc_pututline32 (&in32);
+      buffer = out32p != NULL ? (struct utmp *) data : NULL;
+    }
+  else
+#endif
+    buffer = __libc_pututline (data);
 
   __libc_lock_unlock (__libc_utmp_lock);
 
   return buffer;
 }
 libc_hidden_def (__pututline)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __pututline, pututline, UTMP_COMPAT_BASE);
+#else
 weak_alias (__pututline, pututline)
+#endif
 
 
 void
diff --git a/login/getutid.c b/login/getutid.c
index 0c5c106b59..b96ccb2381 100644
--- a/login/getutid.c
+++ b/login/getutid.c
@@ -18,7 +18,8 @@
 
 #include <stdlib.h>
 #include <utmp.h>
-
+#include <shlib-compat.h>
+#include <utmp-compat.h>
 
 /* Local buffer to store the result.  */
 libc_freeres_ptr (static struct utmp *buffer);
@@ -40,4 +41,8 @@ __getutid (const struct utmp *id)
   return result;
 }
 libc_hidden_def (__getutid)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutid, getutid, UTMP_COMPAT_BASE);
+#else
 weak_alias (__getutid, getutid)
+#endif
diff --git a/login/getutid_r.c b/login/getutid_r.c
index c655c4f56b..5516791775 100644
--- a/login/getutid_r.c
+++ b/login/getutid_r.c
@@ -21,9 +21,10 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <utmp.h>
-
-#include "utmp-private.h"
-
+#include <utmp-compat.h>
+#include <shlib-compat.h>
+#include <utmp-private.h>
+#include <utmp-convert.h>
 
 /* We have to use the lock in getutent_r.c.  */
 __libc_lock_define (extern, __libc_utmp_lock attribute_hidden)
@@ -48,11 +49,35 @@ __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result)
 
   __libc_lock_lock (__libc_utmp_lock);
 
-  retval = __libc_getutid_r (id, buffer, result);
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+  if (__libc_utmpname_mode == UTMPNAME_TIME32)
+    {
+      struct utmp32 in32;
+      struct utmp32 out32;
+      struct utmp32 *out32p;
+
+      __utmp_convert64to32 (id, &in32);
+
+      retval =  __libc_getutid32_r (&in32, &out32, &out32p);
+      if (retval == 0)
+	{
+	  __utmp_convert32to64 (out32p, buffer);
+	  *result = buffer;
+	}
+      else
+	*result = NULL;
+    }
+  else
+#endif
+    retval = __libc_getutid_r (id, buffer, result);
 
   __libc_lock_unlock (__libc_utmp_lock);
 
   return retval;
 }
 libc_hidden_def (__getutid_r)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutid_r, getutid_r, UTMP_COMPAT_BASE);
+#else
 weak_alias (__getutid_r, getutid_r)
+#endif
diff --git a/login/getutline.c b/login/getutline.c
index 34ea8611e2..dea5edffd8 100644
--- a/login/getutline.c
+++ b/login/getutline.c
@@ -18,7 +18,8 @@
 
 #include <stdlib.h>
 #include <utmp.h>
-
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 /* Local buffer to store the result.  */
 libc_freeres_ptr (static struct utmp *buffer);
@@ -41,4 +42,8 @@ __getutline (const struct utmp *line)
   return result;
 }
 libc_hidden_def (__getutline)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutline, getutline, UTMP_COMPAT_BASE);
+#else
 weak_alias (__getutline, getutline)
+#endif
diff --git a/login/getutline_r.c b/login/getutline_r.c
index 41ad9ff12b..2f6a37e476 100644
--- a/login/getutline_r.c
+++ b/login/getutline_r.c
@@ -20,9 +20,10 @@
 #include <errno.h>
 #include <libc-lock.h>
 #include <utmp.h>
-
-#include "utmp-private.h"
-
+#include <utmp-compat.h>
+#include <shlib-compat.h>
+#include <utmp-private.h>
+#include <utmp-convert.h>
 
 /* We have to use the lock in getutent_r.c.  */
 __libc_lock_define (extern, __libc_utmp_lock attribute_hidden)
@@ -36,11 +37,35 @@ __getutline_r (const struct utmp *line, struct utmp *buffer,
 
   __libc_lock_lock (__libc_utmp_lock);
 
-  retval = __libc_getutline_r (line, buffer, result);
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+  if (__libc_utmpname_mode == UTMPNAME_TIME32)
+   {
+      struct utmp32 in32;
+      struct utmp32 out32;
+      struct utmp32 *out32p;
+
+      __utmp_convert64to32 (line, &in32);
+
+      retval =  __libc_getutline32_r (&in32, &out32, &out32p);
+      if (retval == 0)
+	{
+	  __utmp_convert32to64 (out32p, buffer);
+	  *result = buffer;
+	}
+      else
+	*result = NULL;
+    }
+  else
+#endif
+    retval = __libc_getutline_r (line, buffer, result);
 
   __libc_lock_unlock (__libc_utmp_lock);
 
   return retval;
 }
 libc_hidden_def (__getutline_r)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutline_r, getutline_r, UTMP_COMPAT_BASE);
+#else
 weak_alias (__getutline_r, getutline_r)
+#endif
diff --git a/login/getutmp.c b/login/getutmp.c
index 3058a93d1b..d521e5e51e 100644
--- a/login/getutmp.c
+++ b/login/getutmp.c
@@ -21,6 +21,8 @@
 #define getutmpx __redirect_getutmpx
 #include <utmpx.h>
 #undef getutmpx
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 #define CHECK_SIZE_AND_OFFSET(field) \
   _Static_assert (sizeof ((struct utmp){0}.field)		\
@@ -59,5 +61,11 @@ __getutmp (const struct utmpx *utmpx, struct utmp *utmp)
   utmp->ut_tv.tv_usec = utmpx->ut_tv.tv_usec;
 }
 
-weak_alias (__getutmp, getutmp)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutmp, getutmp, UTMP_COMPAT_BASE);
+strong_alias (__getutmp, __getutmpx)
+versioned_symbol (libc, __getutmpx, getutmpx, UTMP_COMPAT_BASE);
+#else
+strong_alias (__getutmp, getutmp)
 strong_alias (__getutmp, getutmpx)
+#endif
diff --git a/login/getutxent.c b/login/getutxent.c
index ca90a13d4b..505b2b6441 100644
--- a/login/getutxent.c
+++ b/login/getutxent.c
@@ -18,9 +18,16 @@
 
 #include <utmp.h>
 #include <utmpx.h>
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 struct utmpx *
-getutxent (void)
+__getutxent (void)
 {
   return (struct utmpx *) __getutent ();
 }
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutxent, getutxent, UTMP_COMPAT_BASE);
+#else
+weak_alias (__getutxent, getutxent)
+#endif
diff --git a/login/getutxid.c b/login/getutxid.c
index d53993f5e9..871aef11d8 100644
--- a/login/getutxid.c
+++ b/login/getutxid.c
@@ -18,9 +18,16 @@
 
 #include <utmp.h>
 #include <utmpx.h>
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 struct utmpx *
-getutxid (const struct utmpx *id)
+__getutxid (const struct utmpx *id)
 {
   return (struct utmpx *) __getutid ((const struct utmp *) id);
 }
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutxid, getutxid, UTMP_COMPAT_BASE);
+#else
+weak_alias (__getutxid, getutxid)
+#endif
diff --git a/login/getutxline.c b/login/getutxline.c
index f1d28211b0..d212217285 100644
--- a/login/getutxline.c
+++ b/login/getutxline.c
@@ -18,9 +18,16 @@
 
 #include <utmp.h>
 #include <utmpx.h>
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 struct utmpx *
-getutxline (const struct utmpx *line)
+__getutxline (const struct utmpx *line)
 {
   return (struct utmpx *) __getutline ((const struct utmp *) line);
 }
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __getutxline, getutxline, UTMP_COMPAT_BASE);
+#else
+weak_alias (__getutxline, getutxline)
+#endif
diff --git a/login/login.c b/login/login.c
index cc26d2982b..ca2a99210f 100644
--- a/login/login.c
+++ b/login/login.c
@@ -23,6 +23,8 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <utmp.h>
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 
 /* Return the result of ttyname in the buffer pointed to by TTY, which should
@@ -78,7 +80,7 @@ tty_name (int fd, char **tty, size_t buf_len)
 }
 \f
 void
-login (const struct utmp *ut)
+__login (const struct utmp *ut)
 {
 #ifdef PATH_MAX
   char _tty[PATH_MAX + UT_LINESIZE];
@@ -137,3 +139,9 @@ login (const struct utmp *ut)
   /* Update the WTMP file.  Here we have to add a new entry.  */
   updwtmp (_PATH_WTMP, &copy);
 }
+hidden_def (__login)
+#if SHLIB_COMPAT(libutil, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libutil, __login, login, UTMP_COMPAT_BASE);
+#else
+weak_alias (__login, login)
+#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/login32.c b/login/login32.c
similarity index 72%
rename from sysdeps/unix/sysv/linux/s390/s390-32/login32.c
rename to login/login32.c
index 22f908df88..30ea96cfa4 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/login32.c
+++ b/login/login32.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
+/* Write utmp and wtmp entries, 32-bit time compat version.
+   Copyright (C) 2008-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -16,21 +16,23 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <sys/types.h>
 #include <utmp.h>
-#include <libc-symbols.h>
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 #include "utmp32.h"
 #include "utmp-convert.h"
 
+#if SHLIB_COMPAT(libutil, GLIBC_2_0, UTMP_COMPAT_BASE)
 /* Write the given entry into utmp and wtmp.  */
 void
 login32 (const struct utmp32 *entry)
 {
   struct utmp in64;
 
-  utmp_convert32to64 (entry, &in64);
-  login (&in64);
+  __utmp_convert32to64 (entry, &in64);
+  __login (&in64);
 }
 
-symbol_version (login32, login, GLIBC_2.0);
+compat_symbol (libutil, login32, login, GLIBC_2_0);
+#endif
diff --git a/login/pututxline.c b/login/pututxline.c
index eec8851d45..ddd6330811 100644
--- a/login/pututxline.c
+++ b/login/pututxline.c
@@ -18,9 +18,16 @@
 
 #include <utmp.h>
 #include <utmpx.h>
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 struct utmpx *
-pututxline (const struct utmpx *utmpx)
+__pututxline (const struct utmpx *utmpx)
 {
   return (struct utmpx *) __pututline ((const struct utmp *) utmpx);
 }
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __pututxline, pututxline, UTMP_COMPAT_BASE);
+#else
+weak_alias (__pututxline, pututxline)
+#endif
diff --git a/login/tst-utmp-default.c b/login/tst-utmp-default.c
new file mode 100644
index 0000000000..2bc84404e3
--- /dev/null
+++ b/login/tst-utmp-default.c
@@ -0,0 +1,292 @@
+/* Tests for UTMP functions using default and old UTMP_FILE.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <string.h>
+#include <utmp.h>
+
+#include <support/check.h>
+#include <support/temp_file.h>
+
+/* The default utmp{x} functions read and write the exported 64-bit time_t
+   utmp/utmpx struct as default with the only exception when the old
+   UTMP_FILE ('/var/run/utmp') or WUTMP_FILE ('/var/run/wtmp') is set
+   explicitly with utmpname or updwtmp.  In this case old 32-bit time_t
+   entries are read / write instead.  */
+
+static struct utmp entry[] =
+{
+#define UT(a)  .ut_tv = { .tv_sec = (a)}
+
+  { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) },
+  { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) },
+  { .ut_type = INIT_PROCESS, .ut_pid = 5, .ut_id = "si", UT(3000) },
+  { .ut_type = LOGIN_PROCESS, .ut_pid = 23, .ut_line = "tty1", .ut_id = "1",
+    .ut_user = "LOGIN", UT(4000) },
+  { .ut_type = USER_PROCESS, .ut_pid = 24, .ut_line = "tty2", .ut_id = "2",
+    .ut_user = "albert", UT(8000) },
+  { .ut_type = USER_PROCESS, .ut_pid = 196, .ut_line = "ttyp0", .ut_id = "p0",
+    .ut_user = "niels", UT(10000) },
+  { .ut_type = DEAD_PROCESS, .ut_line = "ttyp1", .ut_id = "p1", UT(16000) },
+  { .ut_type = EMPTY },
+  { .ut_type = EMPTY }
+};
+const size_t entry_size = sizeof (entry) / sizeof (entry[0]);
+
+static time_t entry_time = 20000;
+static pid_t entry_pid = 234;
+
+static void
+compare_utmp (const struct utmp *left, const struct utmp *right)
+{
+  TEST_COMPARE (left->ut_type, right->ut_type);
+  TEST_COMPARE (left->ut_pid, right->ut_pid);
+  TEST_COMPARE_BLOB (left->ut_line, sizeof (left->ut_line),
+		     right->ut_line, sizeof (right->ut_line));
+  TEST_COMPARE_BLOB (left->ut_id, sizeof (left->ut_id),
+		     right->ut_id, sizeof (right->ut_id));
+  TEST_COMPARE_BLOB (left->ut_user, sizeof (left->ut_user),
+		     right->ut_user, sizeof (right->ut_user));
+  TEST_COMPARE_BLOB (left->ut_host, sizeof (left->ut_host),
+		     right->ut_host, sizeof (right->ut_host));
+  TEST_COMPARE (left->ut_exit.e_termination, right->ut_exit.e_termination);
+  TEST_COMPARE (left->ut_exit.e_exit, right->ut_exit.e_exit);
+  TEST_COMPARE (left->ut_tv.tv_sec, right->ut_tv.tv_sec);
+  TEST_COMPARE (left->ut_tv.tv_usec, right->ut_tv.tv_usec);
+  TEST_COMPARE_BLOB (left->ut_addr_v6, sizeof (left->ut_addr_v6),
+		     right->ut_addr_v6, sizeof (right->ut_addr_v6));
+}
+
+static void
+do_init (void)
+{
+  setutent ();
+
+  for (int n = 0; n < entry_size; n++)
+    TEST_VERIFY (pututline (&entry[n]) != NULL);
+
+  endutent ();
+}
+
+static void
+do_check (void)
+{
+  struct utmp *ut;
+  int n;
+
+  setutent ();
+
+  n = 0;
+  while ((ut = getutent ()))
+    {
+      TEST_VERIFY (n <= entry_size);
+      compare_utmp (ut, &entry[n]);
+      n++;
+    }
+  TEST_COMPARE (n, entry_size);
+
+  endutent ();
+}
+
+static void
+simulate_login (const char *line, const char *user)
+{
+  for (int n = 0; n < entry_size; n++)
+    {
+      if (strcmp (line, entry[n].ut_line) == 0
+	  || entry[n].ut_type == DEAD_PROCESS)
+	{
+	  if (entry[n].ut_pid == DEAD_PROCESS)
+	    entry[n].ut_pid = (entry_pid += 27);
+	  entry[n].ut_type = USER_PROCESS;
+	  strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user));
+	  entry[n].ut_tv.tv_sec = (entry_time += 1000);
+	  setutent ();
+
+	  TEST_VERIFY (pututline (&entry[n]) != NULL);
+
+	  endutent ();
+
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("no entries available");
+}
+
+static void
+simulate_logout (const char *line)
+{
+  int n;
+
+  for (n = 0; n < entry_size; n++)
+    {
+      if (strcmp (line, entry[n].ut_line) == 0)
+	{
+	  entry[n].ut_type = DEAD_PROCESS;
+	  strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user));
+          entry[n].ut_tv.tv_sec = (entry_time += 1000);
+	  setutent ();
+
+	  TEST_VERIFY (pututline (&entry[n]) != NULL);
+
+	  endutent ();
+
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("no entries available");
+}
+
+static void
+check_login (const char *line)
+{
+  struct utmp *up;
+  struct utmp ut;
+
+  setutent ();
+
+  strcpy (ut.ut_line, line);
+  up = getutline (&ut);
+  TEST_VERIFY (up != NULL);
+
+  endutent ();
+
+  for (int n = 0; n < entry_size; n++)
+    {
+      if (strcmp (line, entry[n].ut_line) == 0)
+	{
+	  compare_utmp (up, &entry[n]);
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("bogus entry for line `%s'", line);
+}
+
+static void
+check_logout (const char *line)
+{
+  struct utmp ut;
+
+  setutent ();
+
+  strcpy (ut.ut_line, line);
+  TEST_VERIFY (getutline (&ut) == NULL);
+
+  endutent ();
+}
+
+static void
+check_id (const char *id)
+{
+  struct utmp *up;
+  struct utmp ut;
+
+  setutent ();
+
+  ut.ut_type = USER_PROCESS;
+  strcpy (ut.ut_id, id);
+  up = getutid (&ut);
+  TEST_VERIFY (up != NULL);
+
+  endutent ();
+
+  for (int n = 0; n < entry_size; n++)
+    {
+      if (strcmp (id, entry[n].ut_id) == 0)
+	{
+	  compare_utmp (up, &entry[n]);
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("bogus entry for ID `%s'", id);
+}
+
+static void
+check_type (int type)
+{
+  struct utmp *up;
+  struct utmp ut;
+  int n;
+
+  setutent ();
+
+  ut.ut_type = type;
+  up = getutid (&ut);
+  TEST_VERIFY (up != NULL);
+
+  endutent ();
+
+  for (n = 0; n < entry_size; n++)
+    {
+      if (type == entry[n].ut_type)
+	{
+	  compare_utmp (up, &entry[n]);
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("bogus entry for type `%d'", type);
+}
+
+static void
+run_test (void)
+{
+  do_init ();
+  do_check ();
+
+  simulate_login ("tty1", "erwin");
+  do_check ();
+
+  simulate_login ("ttyp1", "paul");
+  do_check ();
+
+  simulate_logout ("tty2");
+  do_check ();
+
+  simulate_logout ("ttyp0");
+  do_check ();
+
+  simulate_login ("ttyp2", "richard");
+  do_check ();
+
+  check_login ("tty1");
+  check_logout ("ttyp0");
+  check_id ("p1");
+  check_id ("2");
+  check_id ("si");
+  check_type (BOOT_TIME);
+  check_type (RUN_LVL);
+}
+
+static int
+do_test (void)
+{
+  utmpname (UTMP_FILE);
+  run_test ();
+
+  utmpname ("/var/run/utmp");
+  run_test ();
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/login/tst-utmp-default.root/tst-utmp-default.script b/login/tst-utmp-default.root/tst-utmp-default.script
new file mode 100644
index 0000000000..26ef984f5f
--- /dev/null
+++ b/login/tst-utmp-default.root/tst-utmp-default.script
@@ -0,0 +1,10 @@
+# We create empty UTMP_FILE and WTMP_FILE
+mkdirp 0755 /var/run
+touch  0664 /var/run/utmp.v2
+touch  0664 /var/run/wtmp.v2
+# Same for the old files as well
+touch  0664 /var/run/utmp
+touch  0664 /var/run/wtmp
+
+# Must run localedef as root to write into default paths.
+su
diff --git a/login/tst-utmp32.c b/login/tst-utmp32.c
new file mode 100644
index 0000000000..48dc902bde
--- /dev/null
+++ b/login/tst-utmp32.c
@@ -0,0 +1,325 @@
+/* Tests for compat UTMP functions.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+
+#include <shlib-compat.h>
+
+#if TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_33)
+
+/* The test check the compat utmp/utmpx routines for the underlying two
+   operation modes:
+
+   1. Use the default UTMP_FILE which uses the default code path which
+      read/write 64-bit entries and converts to 32-bit time_t utmp/utmpx
+      entries.
+
+   2. Set a non default path with utmpname, which uses the comapt code
+      path to read/write 32-bit time_t utmp/utmpx entres.  */
+
+# include <stdlib.h>
+# include <string.h>
+# include <utmp.h>
+
+# include <support/check.h>
+# include <support/temp_file.h>
+# include <array_length.h>
+
+# include <utmp32.h>
+
+compat_symbol_reference (libc, setutent,  setutent,  GLIBC_2_0);
+compat_symbol_reference (libc, pututline, pututline, GLIBC_2_0);
+compat_symbol_reference (libc, getutline, getutline, GLIBC_2_0);
+compat_symbol_reference (libc, getutent,  getutent,  GLIBC_2_0);
+compat_symbol_reference (libc, getutid,   getutid,   GLIBC_2_0);
+
+static struct utmp32 entry[] =
+{
+#define UT(a)  .ut_tv = { .tv_sec = (a)}
+
+  { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) },
+  { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) },
+  { .ut_type = INIT_PROCESS, .ut_pid = 5, .ut_id = "si", UT(3000) },
+  { .ut_type = LOGIN_PROCESS, .ut_pid = 23, .ut_line = "tty1", .ut_id = "1",
+    .ut_user = "LOGIN", UT(4000) },
+  { .ut_type = USER_PROCESS, .ut_pid = 24, .ut_line = "tty2", .ut_id = "2",
+    .ut_user = "albert", UT(8000) },
+  { .ut_type = USER_PROCESS, .ut_pid = 196, .ut_line = "ttyp0", .ut_id = "p0",
+    .ut_user = "niels", UT(10000) },
+  { .ut_type = DEAD_PROCESS, .ut_line = "ttyp1", .ut_id = "p1", UT(16000) },
+  { .ut_type = EMPTY },
+  { .ut_type = EMPTY }
+};
+
+static time_t entry_time = 20000;
+static pid_t entry_pid = 234;
+
+#include <stdio.h>
+
+static void
+compare_utmp32 (const struct utmp32 *left, const struct utmp32 *right)
+{
+  TEST_COMPARE (left->ut_type, right->ut_type);
+  TEST_COMPARE (left->ut_pid, right->ut_pid);
+  TEST_COMPARE_BLOB (left->ut_line, sizeof (left->ut_line),
+		     right->ut_line, sizeof (right->ut_line));
+  TEST_COMPARE_BLOB (left->ut_id, sizeof (left->ut_id),
+		     right->ut_id, sizeof (right->ut_id));
+  TEST_COMPARE_BLOB (left->ut_user, sizeof (left->ut_user),
+		     right->ut_user, sizeof (right->ut_user));
+  TEST_COMPARE_BLOB (left->ut_host, sizeof (left->ut_host),
+		     right->ut_host, sizeof (right->ut_host));
+  TEST_COMPARE (left->ut_exit.e_termination, right->ut_exit.e_termination);
+  TEST_COMPARE (left->ut_exit.e_exit, right->ut_exit.e_exit);
+  TEST_COMPARE (left->ut_tv.tv_sec, right->ut_tv.tv_sec);
+  TEST_COMPARE (left->ut_tv.tv_usec, right->ut_tv.tv_usec);
+  TEST_COMPARE_BLOB (left->ut_addr_v6, sizeof (left->ut_addr_v6),
+		     right->ut_addr_v6, sizeof (right->ut_addr_v6));
+}
+
+static void
+do_init (void)
+{
+  setutent ();
+
+  for (int n = 0; n < array_length (entry); n++)
+    TEST_VERIFY (pututline ((const struct utmp *) &entry[n]) != NULL);
+
+  endutent ();
+}
+
+static void
+do_check (void)
+{
+  struct utmp32 *ut;
+  int n;
+
+  setutent ();
+
+  n = 0;
+  while ((ut = (struct utmp32 *) getutent ()))
+    {
+      TEST_VERIFY (n <= array_length (entry));
+      compare_utmp32 (ut, &entry[n]);
+      n++;
+    }
+  TEST_COMPARE (n, array_length (entry));
+
+  endutent ();
+}
+
+static void
+simulate_login (const char *line, const char *user)
+{
+  for (int n = 0; n <array_length (entry); n++)
+    {
+      if (strcmp (line, entry[n].ut_line) == 0
+	  || entry[n].ut_type == DEAD_PROCESS)
+	{
+	  if (entry[n].ut_pid == DEAD_PROCESS)
+	    entry[n].ut_pid = (entry_pid += 27);
+	  entry[n].ut_type = USER_PROCESS;
+	  strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user));
+	  entry[n].ut_tv.tv_sec = (entry_time += 1000);
+	  setutent ();
+
+	  TEST_VERIFY (pututline ((const struct utmp *) &entry[n]) != NULL);
+
+	  endutent ();
+
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("no entries available");
+}
+
+static void
+simulate_logout (const char *line)
+{
+  int n;
+
+  for (n = 0; n < array_length (entry); n++)
+    {
+      if (strcmp (line, entry[n].ut_line) == 0)
+	{
+	  entry[n].ut_type = DEAD_PROCESS;
+	  strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user));
+          entry[n].ut_tv.tv_sec = (entry_time += 1000);
+	  setutent ();
+
+	  TEST_VERIFY (pututline ((const struct utmp *) &entry[n]) != NULL);
+
+	  endutent ();
+
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("no entries available");
+}
+
+static void
+check_login (const char *line)
+{
+  struct utmp32 *up;
+  struct utmp32 ut;
+
+  setutent ();
+
+  strcpy (ut.ut_line, line);
+  up = (struct utmp32 *) getutline ((const struct utmp *) &ut);
+  TEST_VERIFY (up != NULL);
+
+  endutent ();
+
+  for (int n = 0; n < array_length (entry); n++)
+    {
+      if (strcmp (line, entry[n].ut_line) == 0)
+	{
+	  compare_utmp32 (up, &entry[n]);
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("bogus entry for line `%s'", line);
+}
+
+static void
+check_logout (const char *line)
+{
+  struct utmp32 ut;
+
+  setutent ();
+
+  strcpy (ut.ut_line, line);
+  TEST_VERIFY (getutline ((const struct utmp *) &ut) == NULL);
+
+  endutent ();
+}
+
+static void
+check_id (const char *id)
+{
+  struct utmp32 *up;
+  struct utmp32 ut;
+
+  setutent ();
+
+  ut.ut_type = USER_PROCESS;
+  strcpy (ut.ut_id, id);
+  up = (struct utmp32 *) getutid ((const struct utmp *) &ut);
+  TEST_VERIFY (up != NULL);
+
+  endutent ();
+
+  for (int n = 0; n < array_length (entry); n++)
+    {
+      if (strcmp (id, entry[n].ut_id) == 0)
+	{
+	  compare_utmp32 (up, &entry[n]);
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("bogus entry for ID `%s'", id);
+}
+
+static void
+check_type (int type)
+{
+  struct utmp32 *up;
+  struct utmp32 ut;
+  int n;
+
+  setutent ();
+
+  ut.ut_type = type;
+  up = (struct utmp32 *) getutid ((const struct utmp *) &ut);
+  TEST_VERIFY (up != NULL);
+
+  endutent ();
+
+  for (n = 0; n < array_length (entry); n++)
+    {
+      if (type == entry[n].ut_type)
+	{
+	  compare_utmp32 (up, &entry[n]);
+	  return;
+	}
+    }
+
+  FAIL_EXIT1 ("bogus entry for type `%d'", type);
+}
+
+static char *name;
+
+static void
+do_prepare (int argc, char **argv)
+{
+  int fd = create_temp_file ("tst-utmp32.", &name);
+  TEST_VERIFY_EXIT (fd != -1);
+}
+#define PREPARE do_prepare
+
+static void
+run_test (void)
+{
+  do_init ();
+  do_check ();
+
+  simulate_login ("tty1", "erwin");
+  do_check ();
+
+  simulate_login ("ttyp1", "paul");
+  do_check ();
+
+  simulate_logout ("tty2");
+  do_check ();
+
+  simulate_logout ("ttyp0");
+  do_check ();
+
+  simulate_login ("ttyp2", "richard");
+  do_check ();
+
+  check_login ("tty1");
+  check_logout ("ttyp0");
+  check_id ("p1");
+  check_id ("2");
+  check_id ("si");
+  check_type (BOOT_TIME);
+  check_type (RUN_LVL);
+}
+#endif
+
+static int
+do_test (void)
+{
+#if TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_33)
+  run_test ();
+
+  utmpname (name);
+  run_test ();
+
+  return 0;
+#else
+  return EXIT_UNSUPPORTED;
+#endif
+}
+
+#include <support/test-driver.c>
diff --git a/login/tst-utmp32.root/tst-utmp32.script b/login/tst-utmp32.root/tst-utmp32.script
new file mode 100644
index 0000000000..4aadc63335
--- /dev/null
+++ b/login/tst-utmp32.root/tst-utmp32.script
@@ -0,0 +1,7 @@
+# We create empty UTMP_FILE and WTMP_FILE
+mkdirp 0755 /var/run
+touch  0664 /var/run/utmp.v2
+touch  0664 /var/run/wtmp.v2
+
+# Must run localedef as root to write into default paths.
+su
diff --git a/login/updwtmp.c b/login/updwtmp.c
index 42a2152b60..7e6fb7ccc9 100644
--- a/login/updwtmp.c
+++ b/login/updwtmp.c
@@ -19,16 +19,31 @@
 #include <utmp.h>
 #include <string.h>
 #include <unistd.h>
-
-#include "utmp-private.h"
+#include <utmp-private.h>
 #include <utmp-path.h>
+#include <utmp-compat.h>
+#include <utmp-convert.h>
+#include <shlib-compat.h>
 
 void
 __updwtmp (const char *wtmp_file, const struct utmp *utmp)
 {
-  const char *file_name = utmp_file_name_time32 (wtmp_file);
-
-  __libc_updwtmp (file_name, utmp);
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+  if (strcmp (wtmp_file, _PATH_WTMP_BASE) == 0
+      || strcmp (wtmp_file, _PATH_WTMP_BASE) == 0)
+    {
+      const char *file_name = utmp_file_name_time32 (wtmp_file);
+      struct utmp32 in32;
+      __utmp_convert64to32 (utmp, &in32);
+      __libc_updwtmp32 (file_name, &in32);
+    }
+  else
+#endif
+    __libc_updwtmp (wtmp_file, utmp);
 }
 libc_hidden_def (__updwtmp)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __updwtmp, updwtmp, UTMP_COMPAT_BASE);
+#else
 weak_alias (__updwtmp, updwtmp)
+#endif
diff --git a/login/updwtmpx.c b/login/updwtmpx.c
index f95306b621..3f1dbb363b 100644
--- a/login/updwtmpx.c
+++ b/login/updwtmpx.c
@@ -18,9 +18,16 @@
 
 #include <utmp.h>
 #include <utmpx.h>
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 void
-updwtmpx (const char *wtmpx_file, const struct utmpx *utmpx)
+__updwtmpx (const char *wtmpx_file, const struct utmpx *utmpx)
 {
   __updwtmp (wtmpx_file, (const struct utmp *) utmpx);
 }
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+versioned_symbol (libc, __updwtmpx, updwtmpx, UTMP_COMPAT_BASE);
+#else
+weak_alias (__updwtmpx, updwtmpx)
+#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/utmp-convert.h b/login/utmp-convert.c
similarity index 58%
rename from sysdeps/unix/sysv/linux/s390/s390-32/utmp-convert.h
rename to login/utmp-convert.c
index 00d2192ee3..284207968d 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmp-convert.h
+++ b/login/utmp-convert.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
+/* Converto to/from 64-bit to 32-bit time_t utmp/utmpx struct.
+   Copyright (C) 2008-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -16,71 +16,42 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-
-/* This file provides functions converting between the 32 and 64 bit
-   struct utmp variants.  */
-
-#ifndef _UTMP_CONVERT_H
-#define _UTMP_CONVERT_H 1
-
 #include <string.h>
-
-#include "utmp32.h"
+#include <utmp-convert.h>
 
 /* Convert the 64 bit struct utmp value in FROM to the 32 bit version
    returned in TO.  */
-static inline void
-utmp_convert64to32 (const struct utmp *from, struct utmp32 *to)
+void
+__utmp_convert64to32 (const struct utmp *from, struct utmp32 *to)
 {
-#if _HAVE_UT_TYPE - 0
   to->ut_type = from->ut_type;
-#endif
-#if _HAVE_UT_PID - 0
   to->ut_pid = from->ut_pid;
-#endif
   memcpy (to->ut_line, from->ut_line, UT_LINESIZE);
   memcpy (to->ut_user, from->ut_user, UT_NAMESIZE);
-#if _HAVE_UT_ID - 0
   memcpy (to->ut_id, from->ut_id, 4);
-#endif
-#if _HAVE_UT_HOST - 0
   memcpy (to->ut_host, from->ut_host, UT_HOSTSIZE);
-#endif
   to->ut_exit = from->ut_exit;
-  to->ut_session = (int32_t) from->ut_session;
-#if _HAVE_UT_TV - 0
-  to->ut_tv.tv_sec = (int32_t) from->ut_tv.tv_sec;
-  to->ut_tv.tv_usec = (int32_t) from->ut_tv.tv_usec;
-#endif
+  to->ut_session = from->ut_session;
+  to->ut_tv.tv_sec = from->ut_tv.tv_sec;
+  to->ut_tv.tv_usec = from->ut_tv.tv_usec;
   memcpy (to->ut_addr_v6, from->ut_addr_v6, 4 * 4);
 }
 
 /* Convert the 32 bit struct utmp value in FROM to the 64 bit version
    returned in TO.  */
-static inline void
-utmp_convert32to64 (const struct utmp32 *from, struct utmp *to)
+void
+__utmp_convert32to64 (const struct utmp32 *from, struct utmp *to)
 {
-#if _HAVE_UT_TYPE - 0
   to->ut_type = from->ut_type;
-#endif
-#if _HAVE_UT_PID - 0
   to->ut_pid = from->ut_pid;
-#endif
   memcpy (to->ut_line, from->ut_line, UT_LINESIZE);
   memcpy (to->ut_user, from->ut_user, UT_NAMESIZE);
-#if _HAVE_UT_ID - 0
   memcpy (to->ut_id, from->ut_id, 4);
-#endif
-#if _HAVE_UT_HOST - 0
   memcpy (to->ut_host, from->ut_host, UT_HOSTSIZE);
-#endif
   to->ut_exit = from->ut_exit;
-  to->ut_session = (int64_t) from->ut_session;
-#if _HAVE_UT_TV - 0
-  to->ut_tv.tv_sec = (int64_t) from->ut_tv.tv_sec;
-  to->ut_tv.tv_usec = (int64_t) from->ut_tv.tv_usec;
-#endif
-  memcpy (to->ut_addr_v6, from->ut_addr_v6, 4 * 4);
+  to->ut_session = from->ut_session;
+  to->ut_tv.tv_sec = from->ut_tv.tv_sec;
+  to->ut_tv.tv_usec = from->ut_tv.tv_usec;
+  memcpy (to->ut_addr_v6, from->ut_addr_v6, sizeof (to->ut_addr_v6));
 }
-
-#endif /* utmp-convert.h */
+libc_hidden_def (__utmp_convert32to64)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutent.c b/login/utmp-convert.h
similarity index 59%
rename from sysdeps/unix/sysv/linux/s390/s390-32/getutent.c
rename to login/utmp-convert.h
index 615312ed39..2b64dc8d5a 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutent.c
+++ b/login/utmp-convert.h
@@ -16,17 +16,23 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <stdlib.h>
-#include <utmp.h>
 
-#include "utmp-compat.h"
+/* This file provides functions converting between the 32 and 64 bit
+   struct utmp variants.  */
 
-#if defined SHARED
-# undef weak_alias
-# define weak_alias(n,a)
-#endif
-#include "login/getutent.c"
+#ifndef _UTMP_CONVERT_H
+#define _UTMP_CONVERT_H 1
 
-#if defined SHARED
-default_symbol_version (__getutent, getutent, UTMP_COMPAT_BASE);
-#endif
+#include <utmp32.h>
+
+/* Convert the 64 bit struct utmp value in FROM to the 32 bit version
+   returned in TO.  */
+void __utmp_convert64to32 (const struct utmp *from, struct utmp32 *to)
+  attribute_hidden;
+
+/* Convert the 32 bit struct utmp value in FROM to the 64 bit version
+   returned in TO.  */
+void __utmp_convert32to64 (const struct utmp32 *from, struct utmp *to);
+libc_hidden_proto (__utmp_convert32to64);
+
+#endif /* utmp-convert.h */
diff --git a/login/utmp-path.h b/login/utmp-path.h
index c284c8c398..1d1b2b4307 100644
--- a/login/utmp-path.h
+++ b/login/utmp-path.h
@@ -19,8 +19,8 @@
 #ifndef _UTMP_PATH_H
 #define _UTMP_PATH_H 1
 
-#include <string.h>
 #include <unistd.h>
+#include <string.h>
 
 /* The function returns the utmp database for 32-bit utmp{x} entries based
    on FILE_NAME.  If the argument ends with 'x' and the file does not
diff --git a/login/utmp-private.h b/login/utmp-private.h
index fceb7b9551..1a68fdb286 100644
--- a/login/utmp-private.h
+++ b/login/utmp-private.h
@@ -22,23 +22,43 @@
 #define _UTMP_PRIVATE_H	1
 
 #include <utmp.h>
+#include <utmp32.h>
+#include <sys/param.h>
 #include <libc-lock.h>
 
 /* These functions check for initialization, but not perform any
    locking.  */
 int __libc_setutent (void) attribute_hidden;
+int __libc_setutent32 (void) attribute_hidden;
+void __libc_endutent (void) attribute_hidden;
+
 int __libc_getutent_r (struct utmp *, struct utmp **) attribute_hidden;
 int __libc_getutid_r (const struct utmp *, struct utmp *, struct utmp **)
   attribute_hidden;
 int __libc_getutline_r (const struct utmp *, struct utmp *, struct utmp **)
   attribute_hidden;
 struct utmp *__libc_pututline (const struct utmp *) attribute_hidden;
-void __libc_endutent (void) attribute_hidden;
 int __libc_updwtmp (const char *, const struct utmp *) attribute_hidden;
 
+int __libc_getutent32_r (struct utmp32 *, struct utmp32 **) attribute_hidden;
+int __libc_getutid32_r (const struct utmp32 *, struct utmp32 *,
+			struct utmp32 **) attribute_hidden;
+int __libc_getutline32_r (const struct utmp32 *, struct utmp32 *,
+			  struct utmp32 **) attribute_hidden;
+struct utmp32 *__libc_pututline32 (const struct utmp32 *) attribute_hidden;
+int __libc_updwtmp32 (const char *, const struct utmp32 *) attribute_hidden;
+
 /* Current file name.  */
 extern const char *__libc_utmp_file_name attribute_hidden;
 
+enum __libc_utmpname_mode_t
+{
+  UTMPNAME_TIME64,
+  UTMPNAME_TIME32,
+  UTMPNAME_UNDEF
+};
+extern enum __libc_utmpname_mode_t __libc_utmpname_mode attribute_hidden;
+
 /* Locks access to the global data.  */
 __libc_lock_define (extern, __libc_utmp_lock attribute_hidden)
 
diff --git a/login/utmp32.c b/login/utmp32.c
new file mode 100644
index 0000000000..1ab83de23a
--- /dev/null
+++ b/login/utmp32.c
@@ -0,0 +1,245 @@
+/* Compability symbols for utmp with 32-bit entry times.
+   Copyright (C) 2008-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <utmp.h>
+#include <errno.h>
+#include <libc-lock.h>
+
+#include <utmp32.h>
+#include <utmp-convert.h>
+#include <utmp-private.h>
+#include <utmp-path.h>
+
+#include <utmp-compat.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+
+/* The compat utmp{x} functions are used for 32-bit time_t utmp/utmpx struct
+   and they use two operation modes:
+
+   1. Read/write 64-bit utmp{x} entries and convert them to/from 32-bit utmp.
+      This is done for the exported UTMP_FILE / WUTMP_FILE
+      (__libc_utmpname_mode equal to UTMPNAME_TIME64).
+
+   2. Read/write 32-bit utmp if the target file is any other than the default
+      UTMP_FILE / WUTMP_FILE ones.
+
+   It allows maintaining the already set file format for old records, while
+   also allowing reading newer ones (which might be created with call to the
+   default utmp/utmpx symbol version).  */
+
+int
+__getutid32_r (const struct utmp32 *id, struct utmp32 *buffer,
+	       struct utmp32 **result)
+{
+  int r;
+
+  switch (id->ut_type)
+    {
+    case RUN_LVL:
+    case BOOT_TIME:
+    case OLD_TIME:
+    case NEW_TIME:
+    case INIT_PROCESS:
+    case LOGIN_PROCESS:
+    case USER_PROCESS:
+    case DEAD_PROCESS:
+      break;
+    default:
+      __set_errno (EINVAL);
+      *result = NULL;
+      return -1;
+    }
+
+  __libc_lock_lock (__libc_utmp_lock);
+
+  if (__libc_utmpname_mode == UTMPNAME_TIME64)
+   {
+      struct utmp in64;
+      struct utmp out64;
+      struct utmp *out64p;
+
+      __utmp_convert32to64 (id, &in64);
+
+      r =  __libc_getutid_r (&in64, &out64, &out64p);
+      if (r == 0)
+	{
+	  __utmp_convert64to32 (out64p, buffer);
+	  *result = buffer;
+	}
+      else
+	*result = NULL;
+    }
+  else
+    r = __libc_getutid32_r (id, buffer, result);
+
+  __libc_lock_unlock (__libc_utmp_lock);
+
+  return r;
+}
+compat_symbol (libc, __getutid32_r, getutid_r, GLIBC_2_0);
+
+struct utmp32 *
+__getutid32 (const struct utmp32 *id)
+{
+  static struct utmp32 *out32 = NULL;
+  if (out32 == NULL)
+    {
+      out32 = malloc (sizeof (struct utmp32));
+      if (out32 == NULL)
+	return NULL;
+    }
+
+  struct utmp32 *result;
+  return __getutid32_r (id, out32, &result) < 0 ? NULL : result;
+}
+compat_symbol (libc, __getutid32, getutid, GLIBC_2_0);
+
+int
+__getutline32_r (const struct utmp32 *line,
+		 struct utmp32 *buffer, struct utmp32 **result)
+{
+  int r;
+
+  __libc_lock_lock (__libc_utmp_lock);
+
+  if (__libc_utmpname_mode == UTMPNAME_TIME64)
+   {
+      struct utmp in64;
+      struct utmp out64;
+      struct utmp *out64p;
+
+      __utmp_convert32to64 (line, &in64);
+
+      r =  __libc_getutline_r (&in64, &out64, &out64p);
+      if (r == 0)
+	{
+	  __utmp_convert64to32 (out64p, buffer);
+	  *result = buffer;
+	}
+      else
+	*result = NULL;
+    }
+  else
+    r = __libc_getutline32_r (line, buffer, result);
+
+  __libc_lock_unlock (__libc_utmp_lock);
+
+  return r;
+}
+compat_symbol (libc, __getutline32_r, getutline_r, GLIBC_2_0);
+
+struct utmp32 *
+__getutline32 (const struct utmp32 *line)
+{
+  static struct utmp32 *out32 = NULL;
+  if (out32 == NULL)
+    {
+      out32 = malloc (sizeof (struct utmp32));
+      if (out32 == NULL)
+	return NULL;
+    }
+
+  struct utmp32 *result;
+  return __getutline32_r (line, out32, &result) < 0 ? NULL : result;
+}
+compat_symbol (libc, __getutline32, getutline, GLIBC_2_0);
+
+struct utmp32 *
+__pututline32 (const struct utmp32 *line)
+{
+  struct utmp32 *r;
+
+  __libc_lock_lock (__libc_utmp_lock);
+
+  if (__libc_utmpname_mode == UTMPNAME_TIME64)
+   {
+      struct utmp in64;
+      __utmp_convert32to64 (line, &in64);
+      struct utmp *out64p = __libc_pututline (&in64);
+      r = out64p != NULL ? (struct utmp32 *) line : NULL;
+    }
+  else
+    r = __libc_pututline32 (line);
+
+  __libc_lock_unlock (__libc_utmp_lock);
+
+  return r;
+}
+compat_symbol (libc, __pututline32, pututline, GLIBC_2_0);
+
+int
+__getutent32_r (struct utmp32 *buffer, struct utmp32 **result)
+{
+  int r;
+
+  if (__libc_utmpname_mode == UTMPNAME_TIME64)
+    {
+      struct utmp out64;
+      struct utmp *out64p;
+      r = __libc_getutent_r (&out64, &out64p);
+      if (r == 0)
+	{
+	  __utmp_convert64to32 (out64p, buffer);
+	  *result = buffer;
+	}
+    }
+  else
+    r = __libc_getutent32_r (buffer, result);
+
+  __libc_lock_lock (__libc_utmp_lock);
+
+  return r;
+}
+compat_symbol (libc, __getutent32_r, getutent_r, GLIBC_2_0);
+
+struct utmp32 *
+__getutent32 (void)
+{
+  static struct utmp32 *out32 = NULL;
+  if (out32 == NULL)
+    {
+      out32 = malloc (sizeof (struct utmp32));
+      if (out32 == NULL)
+	return NULL;
+    }
+
+  struct utmp32 *result;
+  return __getutent32_r (out32, &result) < 0 ? NULL : result;
+}
+compat_symbol (libc, __getutent32, getutent, GLIBC_2_0);
+
+void
+__updwtmp32 (const char *wtmp_file, const struct utmp32 *utmp)
+{
+  const char *file_name = utmp_file_name_time32 (wtmp_file);
+
+  if (__libc_utmpname_mode == UTMPNAME_TIME64)
+    {
+      struct utmp in32;
+      __utmp_convert32to64 (utmp, &in32);
+      __libc_updwtmp (file_name, &in32);
+    }
+  else
+    __libc_updwtmp32 (file_name, utmp);
+}
+compat_symbol (libc, __updwtmp32, updwtmp, GLIBC_2_0);
+
+#endif /* SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)   */
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/utmp32.h b/login/utmp32.h
similarity index 78%
rename from sysdeps/unix/sysv/linux/s390/s390-32/utmp32.h
rename to login/utmp32.h
index 046de072de..1ab524f7b8 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmp32.h
+++ b/login/utmp32.h
@@ -47,5 +47,14 @@ struct utmp32
   char __glibc_reserved[20];		/* Reserved for future use.  */
 };
 
+int __getutid32_r (const struct utmp32 *, struct utmp32 *, struct utmp32 **);
+struct utmp32 *__getutid32 (const struct utmp32 *);
+int __getutline32_r (const struct utmp32 *, struct utmp32 *,
+		     struct utmp32 **);
+struct utmp32 *__getutline32 (const struct utmp32 *line);
+struct utmp32 *__pututline32 (const struct utmp32 *line);
+int __getutent32_r (struct utmp32 *, struct utmp32 **);
+struct utmp32 *__getutent32 (void);
+void __updwtmp32 (const char *wtmp_file, const struct utmp32 *utmp);
 
 #endif  /* utmp32.h  */
diff --git a/login/utmp_file.c b/login/utmp_file.c
index 4f4f0cf4e4..c17b4d7af3 100644
--- a/login/utmp_file.c
+++ b/login/utmp_file.c
@@ -17,22 +17,16 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <assert.h>
-#include <errno.h>
 #include <fcntl.h>
-#include <signal.h>
 #include <stdbool.h>
-#include <stdio.h>
 #include <string.h>
-#include <unistd.h>
-#include <utmp.h>
-#include <not-cancel.h>
-#include <kernel-features.h>
-#include <sigsetops.h>
+#include <sys/param.h>
 #include <not-cancel.h>
 
-#include "utmp-private.h"
+#include <utmp-private.h>
 #include <utmp-path.h>
+#include <utmp-compat.h>
+#include <shlib-compat.h>
 
 
 /* Descriptor for the file and position.  */
@@ -40,41 +34,90 @@ static int file_fd = -1;
 static bool file_writable;
 static off64_t file_offset;
 
+
+/* The utmp{x} internal functions work on two operations modes
+
+   1. Read/write 64-bit time utmp{x} entries using the exported
+      'struct utmp{x}'
+
+   2. Read/write 32-bit time utmp{x} entries using the old 'struct utmp32'
+
+   The operation mode mainly change the register size and how to interpret
+   the 'last_entry' buffered record.  */
+enum operation_mode_t
+{
+  UTMP_TIME64,
+  UTMP_TIME32
+};
+
+enum
+{
+  utmp_buffer_size = MAX (sizeof (struct utmp), sizeof (struct utmp32))
+};
+
 /* Cache for the last read entry.  */
-static struct utmp last_entry;
+static char last_entry[utmp_buffer_size];
+
+static inline size_t last_entry_size (enum operation_mode_t mode)
+{
+  return mode == UTMP_TIME64 ? sizeof (struct utmp) : sizeof (struct utmp32);
+}
+
+static inline short int last_entry_type (enum operation_mode_t mode)
+{
+  short int r;
+  if (mode == UTMP_TIME32)
+    memcpy (&r, last_entry + offsetof (struct utmp32, ut_type), sizeof (r));
+  else
+    memcpy (&r, last_entry + offsetof (struct utmp, ut_type), sizeof (r));
+  return r;
+}
+
+static inline const char *last_entry_id (enum operation_mode_t mode)
+{
+  if (mode == UTMP_TIME64)
+   return ((struct utmp *) (last_entry))->ut_id;
+  return ((struct utmp32 *) (last_entry))->ut_id;
+}
+
+static inline const char *last_entry_line (enum operation_mode_t mode)
+{
+  if (mode == UTMP_TIME64)
+   return ((struct utmp *) (last_entry))->ut_line;
+  return ((struct utmp32 *) (last_entry))->ut_line;
+}
 
-/* Returns true if *ENTRY matches last_entry, based on
-   data->ut_type.  */
+/* Returns true if *ENTRY matches last_entry, based on data->ut_type.  */
 static bool
-matches_last_entry (const struct utmp *data)
+matches_last_entry (enum operation_mode_t mode, short int type,
+		    const char *id, const char *line)
 {
   if (file_offset <= 0)
     /* Nothing has been read.  last_entry is stale and cannot match.  */
     return false;
 
-  if (data->ut_type == RUN_LVL
-      || data->ut_type == BOOT_TIME
-      || data->ut_type == OLD_TIME
-      || data->ut_type == NEW_TIME)
-    /* For some entry types, only a type match is required.  */
-    return data->ut_type == last_entry.ut_type;
-  else
-    /* For the process-related entries, a full match is needed.  */
-    return (data->ut_type == INIT_PROCESS
-	    || data->ut_type == LOGIN_PROCESS
-	    || data->ut_type == USER_PROCESS
-	    || data->ut_type == DEAD_PROCESS)
-      && (last_entry.ut_type == INIT_PROCESS
-	  || last_entry.ut_type == LOGIN_PROCESS
-	  || last_entry.ut_type == USER_PROCESS
-	  || last_entry.ut_type == DEAD_PROCESS)
-      && (data->ut_id[0] && last_entry.ut_id[0]
-	  ? strncmp (data->ut_id, last_entry.ut_id,
-		     sizeof last_entry.ut_id)
-	    == 0
-	  : (strncmp (data->ut_line, last_entry.ut_line,
-		      sizeof last_entry.ut_line)
-	     == 0));
+  switch (type)
+    {
+    case RUN_LVL:
+    case BOOT_TIME:
+    case OLD_TIME:
+    case NEW_TIME:
+      /* For some entry types, only a type match is required.  */
+      return type == last_entry_type (mode);
+    default:
+      /* For the process-related entries, a full match is needed.  */
+      return (type == INIT_PROCESS
+	      || type == LOGIN_PROCESS
+	      || type == USER_PROCESS
+	      || type == DEAD_PROCESS)
+	&& (last_entry_type (mode) == INIT_PROCESS
+	    || last_entry_type (mode) == LOGIN_PROCESS
+	    || last_entry_type (mode) == USER_PROCESS
+	    || last_entry_type (mode) == DEAD_PROCESS)
+	&& (id[0] != '\0' && last_entry_id (mode)[0] != '\0'
+	    ? strncmp (id, last_entry_id (mode), 4 * sizeof (char)) == 0
+	    : (strncmp (line, last_entry_id (mode), UT_LINESIZE) == 0));
+    }
 }
 
 /* Locking timeout.  */
@@ -143,14 +186,14 @@ file_unlock (int fd)
   __fcntl64_nocancel (fd, F_SETLKW, &fl);
 }
 
-int
-__libc_setutent (void)
+static int
+internal_setutent (enum operation_mode_t mode)
 {
   if (file_fd < 0)
     {
-      const char *file_name;
-
-      file_name = utmp_file_name_time32 (__libc_utmp_file_name);
+      const char *file_name = mode == UTMP_TIME64
+	?__libc_utmp_file_name
+	: utmp_file_name_time32 (__libc_utmp_file_name);
 
       file_writable = false;
       file_fd = __open_nocancel
@@ -177,40 +220,34 @@ maybe_setutent (void)
    for EOF, and 1 for a successful read.  last_entry and file_offset
    are only updated on a successful and complete read.  */
 static ssize_t
-read_last_entry (void)
+read_last_entry (enum operation_mode_t mode)
 {
-  struct utmp buffer;
-  ssize_t nbytes = __pread64_nocancel (file_fd, &buffer, sizeof (buffer),
-				       file_offset);
+  char buffer[utmp_buffer_size];
+  const size_t size = last_entry_size (mode);
+  ssize_t nbytes = __pread64_nocancel (file_fd, &buffer, size, file_offset);
   if (nbytes < 0)
     return -1;
-  else if (nbytes != sizeof (buffer))
+  else if (nbytes != size)
     /* Assume EOF.  */
     return 0;
   else
     {
-      last_entry = buffer;
-      file_offset += sizeof (buffer);
+      memcpy (last_entry, buffer, size);
+      file_offset += size;
       return 1;
     }
 }
 
-int
-__libc_getutent_r (struct utmp *buffer, struct utmp **result)
+static int
+internal_getutent_r (enum operation_mode_t mode, void *buffer)
 {
   int saved_errno = errno;
 
-  if (!maybe_setutent ())
-    {
-      /* Not available.  */
-      *result = NULL;
-      return -1;
-    }
-
-  if (try_file_lock (file_fd, F_RDLCK))
+  if (!maybe_setutent ()
+      || try_file_lock (file_fd, F_RDLCK))
     return -1;
 
-  ssize_t nbytes = read_last_entry ();
+  ssize_t nbytes = read_last_entry (mode);
   file_unlock (file_fd);
 
   if (nbytes <= 0)		/* Read error or EOF.  */
@@ -220,111 +257,86 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
 	   EOF is treated like an EOF (missing complete record at the
 	   end).  */
 	__set_errno (saved_errno);
-      *result = NULL;
       return -1;
     }
 
-  memcpy (buffer, &last_entry, sizeof (struct utmp));
-  *result = buffer;
-
+  memcpy (buffer, &last_entry, last_entry_size (mode));
   return 0;
 }
 
-
 /* Search for *ID, updating last_entry and file_offset.  Return 0 on
    success and -1 on failure.  Does not perform locking; for that see
    internal_getut_r below.  */
-static int
-internal_getut_nolock (const struct utmp *id)
+static bool
+internal_getut_nolock (enum operation_mode_t mode, short int type,
+		       const char *id, const char *line)
 {
-  while (1)
+  while (true)
     {
-      ssize_t nbytes = read_last_entry ();
+      ssize_t nbytes = read_last_entry (mode);
       if (nbytes < 0)
-	return -1;
+	return false;
       if (nbytes == 0)
 	{
 	  /* End of file reached.  */
 	  __set_errno (ESRCH);
-	  return -1;
+	  return false;
 	}
 
-      if (matches_last_entry (id))
+      if (matches_last_entry (mode, type, id, line))
 	break;
     }
-
-  return 0;
+  return true;
 }
 
 /* Search for *ID, updating last_entry and file_offset.  Return 0 on
    success and -1 on failure.  If the locking operation failed, write
    true to *LOCK_FAILED.  */
-static int
-internal_getut_r (const struct utmp *id, bool *lock_failed)
+static bool
+internal_getut_r (enum operation_mode_t mode, short int type, const char *id,
+		  const char *line)
 {
   if (try_file_lock (file_fd, F_RDLCK))
-    {
-      *lock_failed = true;
-      return -1;
-    }
+    return false;
 
-  int result = internal_getut_nolock (id);
+  bool r = internal_getut_nolock (mode, type, id, line);
   file_unlock (file_fd);
-  return result;
+  return r;
 }
 
-/* For implementing this function we don't use the getutent_r function
-   because we can avoid the reposition on every new entry this way.  */
-int
-__libc_getutid_r (const struct utmp *id, struct utmp *buffer,
-		  struct utmp **result)
+static int
+internal_getutid_r (enum operation_mode_t mode, short int type,
+		    const char *id, const char *line, void *buffer)
 {
   if (!maybe_setutent ())
-    {
-      *result = NULL;
-      return -1;
-    }
+    return -1;
 
   /* We don't have to distinguish whether we can lock the file or
      whether there is no entry.  */
-  bool lock_failed = false;
-  if (internal_getut_r (id, &lock_failed) < 0)
-    {
-      *result = NULL;
-      return -1;
-    }
+  if (! internal_getut_r (mode, type, id, line))
+    return -1;
 
-  memcpy (buffer, &last_entry, sizeof (struct utmp));
-  *result = buffer;
+  memcpy (buffer, &last_entry, last_entry_size (mode));
 
   return 0;
 }
 
 /* For implementing this function we don't use the getutent_r function
    because we can avoid the reposition on every new entry this way.  */
-int
-__libc_getutline_r (const struct utmp *line, struct utmp *buffer,
-		    struct utmp **result)
+static int
+internal_getutline_r (enum operation_mode_t mode, const char *line,
+		      void *buffer)
 {
-  if (!maybe_setutent ())
-    {
-      *result = NULL;
-      return -1;
-    }
-
-  if (try_file_lock (file_fd, F_RDLCK))
-    {
-      *result = NULL;
-      return -1;
-    }
+  if (!maybe_setutent ()
+      || try_file_lock (file_fd, F_RDLCK))
+    return -1;
 
   while (1)
     {
-      ssize_t nbytes = read_last_entry ();
+      ssize_t nbytes = read_last_entry (mode);
       if (nbytes < 0)
 	{
 	  file_unlock (file_fd);
-	  *result = NULL;
 	  return -1;
 	}
       if (nbytes == 0)
@@ -332,48 +344,45 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
 	  /* End of file reached.  */
 	  file_unlock (file_fd);
 	  __set_errno (ESRCH);
-	  *result = NULL;
 	  return -1;
 	}
 
       /* Stop if we found a user or login entry.  */
-      if ((last_entry.ut_type == USER_PROCESS
-	   || last_entry.ut_type == LOGIN_PROCESS)
-	  && (strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line)
-	      == 0))
+      if ((last_entry_type (mode) == USER_PROCESS
+	   || last_entry_type (mode) == LOGIN_PROCESS)
+	  && (strncmp (line, last_entry_line (mode), UT_LINESIZE) == 0))
 	break;
     }
 
   file_unlock (file_fd);
-  memcpy (buffer, &last_entry, sizeof (struct utmp));
-  *result = buffer;
+  memcpy (buffer, &last_entry, last_entry_size (mode));
 
   return 0;
 }
 
-
-struct utmp *
-__libc_pututline (const struct utmp *data)
+static bool
+internal_pututline (enum operation_mode_t mode, short int type,
+		    const char *id, const char *line, const void *data)
 {
   if (!maybe_setutent ())
-    return NULL;
-
-  struct utmp *pbuf;
+    return false;
 
   if (! file_writable)
     {
       /* We must make the file descriptor writable before going on.  */
-      const char *file_name = utmp_file_name_time32 (__libc_utmp_file_name);
+      const char *file_name = mode == UTMP_TIME64
+	? __libc_utmp_file_name
+	: utmp_file_name_time32 (__libc_utmp_file_name);
 
       int new_fd = __open_nocancel
 	(file_name, O_RDWR | O_LARGEFILE | O_CLOEXEC);
       if (new_fd == -1)
-	return NULL;
+	return false;
 
       if (__dup2 (new_fd, file_fd) < 0)
 	{
 	  __close_nocancel_nostatus (new_fd);
-	  return NULL;
+	  return false;
 	}
       __close_nocancel_nostatus (new_fd);
       file_writable = true;
@@ -381,31 +390,32 @@ __libc_pututline (const struct utmp *data)
 
   /* Exclude other writers before validating the cache.  */
   if (try_file_lock (file_fd, F_WRLCK))
-    return NULL;
+    return false;
 
   /* Find the correct place to insert the data.  */
+  const size_t utmp_size = last_entry_size (mode);
   bool found = false;
-  if (matches_last_entry (data))
+  if (matches_last_entry (mode, type, id, line))
     {
       /* Read back the entry under the write lock.  */
-      file_offset -= sizeof (last_entry);
-      ssize_t nbytes = read_last_entry ();
+      file_offset -= utmp_size;
+      ssize_t nbytes = read_last_entry (mode);
       if (nbytes < 0)
 	{
 	  file_unlock (file_fd);
-	  return NULL;
+	  return false;
 	}
 
       if (nbytes == 0)
 	/* End of file reached.  */
 	found = false;
       else
-	found = matches_last_entry (data);
+	found = matches_last_entry (mode, type, id, line);
     }
 
   if (!found)
     /* Search forward for the entry.  */
-    found = internal_getut_nolock (data) >= 0;
+    found = internal_getut_nolock (mode, type, id, line);
 
   off64_t write_offset;
   if (!found)
@@ -416,26 +426,25 @@ __libc_pututline (const struct utmp *data)
       /* Round down to the next multiple of the entry size.  This
 	 ensures any partially-written record is overwritten by the
 	 new record.  */
-      write_offset = (write_offset / sizeof (struct utmp)
-		      * sizeof (struct utmp));
+      write_offset = write_offset / utmp_size * utmp_size;
     }
   else
     /* Overwrite last_entry.  */
-    write_offset = file_offset - sizeof (struct utmp);
+    write_offset = file_offset - utmp_size;
 
   /* Write the new data.  */
   ssize_t nbytes;
   if (__lseek64 (file_fd, write_offset, SEEK_SET) < 0
-      || (nbytes = __write_nocancel (file_fd, data, sizeof (struct utmp))) < 0)
+      || (nbytes = __write_nocancel (file_fd, data, utmp_size)) < 0)
     {
       /* There is no need to recover the file position because all
 	 reads use pread64, and any future write is preceded by
 	 another seek.  */
       file_unlock (file_fd);
-      return NULL;
+      return false;
     }
 
-  if (nbytes != sizeof (struct utmp))
+  if (nbytes != utmp_size)
     {
       /* If we appended a new record this is only partially written.
 	 Remove it.  */
@@ -445,30 +454,18 @@ __libc_pututline (const struct utmp *data)
       /* Assume that the write failure was due to missing disk
 	 space.  */
       __set_errno (ENOSPC);
-      return NULL;
+      return false;
     }
 
   file_unlock (file_fd);
-  file_offset = write_offset + sizeof (struct utmp);
-  pbuf = (struct utmp *) data;
-
-  return pbuf;
-}
+  file_offset = write_offset + utmp_size;
 
-
-void
-__libc_endutent (void)
-{
-  if (file_fd >= 0)
-    {
-      __close_nocancel_nostatus (file_fd);
-      file_fd = -1;
-    }
+  return true;
 }
 
-
-int
-__libc_updwtmp (const char *file, const struct utmp *utmp)
+static int
+internal_updwtmp (enum operation_mode_t mode, const char *file,
+		  const void *utmp)
 {
   int result = -1;
   off64_t offset;
@@ -487,9 +484,10 @@ __libc_updwtmp (const char *file, const struct utmp *utmp)
 
   /* Remember original size of log file.  */
   offset = __lseek64 (fd, 0, SEEK_END);
-  if (offset % sizeof (struct utmp) != 0)
+  const size_t utmp_size = last_entry_size (mode);
+  if (offset % utmp_size != 0)
     {
-      offset -= offset % sizeof (struct utmp);
+      offset -= offset % utmp_size;
       __ftruncate64 (fd, offset);
 
       if (__lseek64 (fd, 0, SEEK_END) < 0)
@@ -499,8 +497,7 @@ __libc_updwtmp (const char *file, const struct utmp *utmp)
   /* Write the entry.  If we can't write all the bytes, reset the file
      size back to the original size.  That way, no partial entries
      will remain.  */
-  if (__write_nocancel (fd, utmp, sizeof (struct utmp))
-      != sizeof (struct utmp))
+  if (__write_nocancel (fd, utmp, utmp_size) != utmp_size)
     {
       __ftruncate64 (fd, offset);
       goto unlock_return;
@@ -516,3 +513,113 @@ unlock_return:
 
   return result;
 }
+
+int
+__libc_setutent (void)
+{
+  return internal_setutent (UTMP_TIME64);
+}
+
+int
+__libc_setutent32 (void)
+{
+  return internal_setutent (UTMP_TIME32);
+}
+
+int
+__libc_getutent_r (struct utmp *buffer, struct utmp **result)
+{
+  int r = internal_getutent_r (UTMP_TIME64, buffer);
+  *result = r == 0 ? buffer : NULL;
+  return r;
+}
+
+/* For implementing this function we don't use the getutent_r function
+   because we can avoid the reposition on every new entry this way.  */
+int
+__libc_getutid_r (const struct utmp *id, struct utmp *buffer,
+		  struct utmp **result)
+{
+  int r = internal_getutid_r (UTMP_TIME64, id->ut_type, id->ut_id,
+			      id->ut_line, buffer);
+  *result = r == 0? buffer : NULL;
+  return r;
+}
+
+/* For implementing this function we don't use the getutent_r function
+   because we can avoid the reposition on every new entry this way.  */
+int
+__libc_getutline_r (const struct utmp *line, struct utmp *buffer,
+		    struct utmp **result)
+{
+  int r = internal_getutline_r (UTMP_TIME64, line->ut_line, buffer);
+  *result = r == 0 ? buffer : NULL;
+  return r;
+}
+
+struct utmp *
+__libc_pututline (const struct utmp *line)
+{
+  return internal_pututline (UTMP_TIME64, line->ut_type, line->ut_id,
+			     line->ut_line, line)
+	 ? (struct utmp *) line : NULL;
+}
+
+void
+__libc_endutent (void)
+{
+  if (file_fd >= 0)
+    {
+      __close_nocancel_nostatus (file_fd);
+      file_fd = -1;
+    }
+}
+
+int
+__libc_updwtmp (const char *file, const struct utmp *utmp)
+{
+  return internal_updwtmp (UTMP_TIME64, file, utmp);
+}
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, UTMP_COMPAT_BASE)
+int
+__libc_getutent32_r (struct utmp32 *buffer, struct utmp32 **result)
+{
+  int r = internal_getutent_r (UTMP_TIME32, buffer);
+  *result = r == 0 ? buffer : NULL;
+  return r;
+}
+
+int
+__libc_getutid32_r (const struct utmp32 *id, struct utmp32 *buffer,
+		    struct utmp32 **result)
+{
+  int r = internal_getutid_r (UTMP_TIME32, id->ut_type, id->ut_id,
+			      id->ut_line, buffer);
+  *result = r == 0 ? buffer : NULL;
+  return r;
+}
+
+int
+__libc_getutline32_r (const struct utmp32 *line, struct utmp32 *buffer,
+		      struct utmp32 **result)
+{
+  int r = internal_getutline_r (UTMP_TIME32, line->ut_line, buffer);
+  *result = r == 0 ? buffer : NULL;
+  return r;
+}
+
+struct utmp32 *
+__libc_pututline32 (const struct utmp32 *line)
+{
+  return internal_pututline (UTMP_TIME32, line->ut_type, line->ut_id,
+			     line->ut_line, line)
+	 ? (struct utmp32 *) line : NULL;
+}
+
+int
+__libc_updwtmp32 (const char *file, const struct utmp32 *utmp)
+{
+  return internal_updwtmp (UTMP_TIME32, file, utmp);
+}
+#endif
diff --git a/login/utmpname.c b/login/utmpname.c
index 90224afb88..0d16178e2c 100644
--- a/login/utmpname.c
+++ b/login/utmpname.c
@@ -29,6 +29,7 @@ static const char default_file_name[] = _PATH_UTMP;
 
 /* Current file name.  */
 const char *__libc_utmp_file_name = (const char *) default_file_name;
+enum __libc_utmpname_mode_t __libc_utmpname_mode = UTMPNAME_TIME64;
 
 /* We have to use the lock in getutent_r.c.  */
 __libc_lock_define (extern, __libc_utmp_lock attribute_hidden)
@@ -66,6 +67,15 @@ __utmpname (const char *file)
 	}
     }
 
+  if (strcmp (__libc_utmp_file_name, _PATH_UTMP) == 0
+      || strcmp (__libc_utmp_file_name, _PATH_WTMP) == 0)
+    __libc_utmpname_mode = UTMPNAME_TIME64;
+  else if (strcmp (__libc_utmp_file_name, _PATH_UTMP_BASE) == 0
+      || strcmp (__libc_utmp_file_name, _PATH_WTMP_BASE) == 0)
+    __libc_utmpname_mode = UTMPNAME_TIME32;
+  else
+    __libc_utmpname_mode = UTMPNAME_UNDEF;
+
   result = 0;
 
 done:
diff --git a/login/utmpx32.c b/login/utmpx32.c
new file mode 100644
index 0000000000..b15c627a2e
--- /dev/null
+++ b/login/utmpx32.c
@@ -0,0 +1,111 @@
+/* Compability symbols for utmpx with 32-bit entry times.
+   Copyright (C) 2008-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <string.h>
+#include <utmp.h>
+#include <errno.h>
+#include <libc-symbols.h>
+
+#include <utmp32.h>
+#include <utmpx32.h>
+
+#include <utmp-compat.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT(libc, GLIBC_2_1, UTMP_COMPAT_BASE)
+
+# define CHECK_SIZE_AND_OFFSET(field) \
+  _Static_assert (sizeof ((struct utmp32){0}.field)		\
+		  == sizeof ((struct utmpx32){0}.field),		\
+		  "sizeof ((struct utmp32){0}." #field " != "	\
+		  "sizeof ((struct utmpx32){0}" #field);	\
+  _Static_assert (offsetof (struct utmp32, field)			\
+		  == offsetof (struct utmpx32, field),		\
+		  "offsetof (struct utmp32, " #field ") != "	\
+		  "offsetof (struct utmpx32, " #field ")");
+
+/* Sanity check to call the utmp symbols.  */
+_Static_assert (sizeof (struct utmpx32) == sizeof (struct utmp32),
+		"sizeof (struct utmpx32) != sizeof (struct utmp32)");
+CHECK_SIZE_AND_OFFSET (ut_type)
+CHECK_SIZE_AND_OFFSET (ut_pid)
+CHECK_SIZE_AND_OFFSET (ut_line)
+CHECK_SIZE_AND_OFFSET (ut_user)
+CHECK_SIZE_AND_OFFSET (ut_id)
+CHECK_SIZE_AND_OFFSET (ut_host)
+CHECK_SIZE_AND_OFFSET (ut_tv)
+
+struct utmpx32 *
+getutxent32 (void)
+{
+  return (struct utmpx32 *) __getutent32 ();
+}
+compat_symbol (libc, getutxent32, getutxent, GLIBC_2_1);
+
+struct utmpx32 *
+getutxid32 (const struct utmpx32 *id)
+{
+  return (struct utmpx32 *) __getutid32 ((const struct utmp32 *) id);
+}
+compat_symbol (libc, getutxid32, getutxid, GLIBC_2_1);
+
+struct utmpx32 *
+getutxline32 (const struct utmpx32 *line)
+{
+  return (struct utmpx32 *) __getutline32 ((const struct utmp32 *) line);
+}
+compat_symbol (libc, getutxline32, getutxline, GLIBC_2_1);
+
+struct utmpx32 *
+pututxline32 (const struct utmpx32 *utmpx)
+{
+  return (struct utmpx32 *) __pututline32 ((const struct utmp32 *) utmpx);
+}
+compat_symbol (libc, pututxline32, pututxline, GLIBC_2_1);
+
+void
+updwtmpx32 (const char *wtmpx_file, const struct utmpx32 *utmpx)
+{
+  __updwtmp32 (wtmpx_file, (const struct utmp32 *) utmpx);
+}
+compat_symbol (libc, updwtmpx32, updwtmpx, GLIBC_2_1);
+
+#endif /* SHLIB_COMPAT(libc, GLIBC_2_1_1, UTMP_COMPAT_BASE)   */
+
+#if SHLIB_COMPAT(libc, GLIBC_2_1_1, UTMP_COMPAT_BASE)
+
+void
+__getutmp32 (const struct utmpx32 *utmpx, struct utmp32 *utmp)
+{
+  memset (utmp, 0, sizeof (struct utmpx32));
+  utmp->ut_type = utmpx->ut_type;
+  utmp->ut_pid = utmpx->ut_pid;
+  memcpy (utmp->ut_line, utmpx->ut_line, sizeof (utmp->ut_line));
+  memcpy (utmp->ut_user, utmpx->ut_user, sizeof (utmp->ut_user));
+  memcpy (utmp->ut_id, utmpx->ut_id, sizeof (utmp->ut_id));
+  memcpy (utmp->ut_host, utmpx->ut_host, sizeof (utmp->ut_host));
+  utmp->ut_tv.tv_sec = utmpx->ut_tv.tv_sec;
+  utmp->ut_tv.tv_usec = utmpx->ut_tv.tv_usec;
+}
+compat_symbol (libc, __getutmp32, getutmp, GLIBC_2_1_1);
+
+strong_alias (__getutmp32, __getutmpx32)
+compat_symbol (libc, __getutmpx32, getutmpx, GLIBC_2_1_1);
+
+#endif /* SHLIB_COMPAT(libc, GLIBC_2_1, UTMP_COMPAT_BASE)   */
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/utmpx32.h b/login/utmpx32.h
similarity index 93%
rename from sysdeps/unix/sysv/linux/s390/s390-32/utmpx32.h
rename to login/utmpx32.h
index ebec44ace6..d27bb11512 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmpx32.h
+++ b/login/utmpx32.h
@@ -36,11 +36,11 @@ struct utmpx32
   char ut_host[__UT_HOSTSIZE];	/* Hostname for remote login.  */
   struct __exit_status ut_exit;	/* Exit status of a process marked
 				   as DEAD_PROCESS.  */
-  __int64_t ut_session;		/* Session ID, used for windowing.  */
+  __int32_t ut_session;		/* Session ID, used for windowing.  */
   struct
   {
-    __int64_t tv_sec;		/* Seconds.  */
-    __int64_t tv_usec;		/* Microseconds.  */
+    __int32_t tv_sec;		/* Seconds.  */
+    __int32_t tv_usec;		/* Microseconds.  */
   } ut_tv;			/* Time entry was made.  */
 
   __int32_t ut_addr_v6[4];	/* Internet address of remote host.  */
diff --git a/sysdeps/generic/paths.h b/sysdeps/generic/paths.h
index 99a791ce31..ab2980e14a 100644
--- a/sysdeps/generic/paths.h
+++ b/sysdeps/generic/paths.h
@@ -61,11 +61,12 @@
 #define	_PATH_TTY	"/dev/tty"
 #define	_PATH_UNIX	"/vmunix"
 #define	_PATH_UTMP_BASE	"/var/run/utmp"
-#define	_PATH_UTMP	_PATH_UTMP_BASE
-#define	_PATH_UTMP_DB	_PATH_UTMP_BASE ".db"
+#define _PATH_WUTMP_VER ".v2"
+#define	_PATH_UTMP	_PATH_UTMP_BASE _PATH_WUTMP_VER
+#define	_PATH_UTMP_DB	_PATH_UTMP_BASE _PATH_WUTMP_VER ".db"
 #define	_PATH_VI	"/usr/bin/vi"
 #define	_PATH_WTMP_BASE	"/var/log/wtmp"
-#define	_PATH_WTMP	_PATH_WTMP_BASE
+#define	_PATH_WTMP	_PATH_WTMP_BASE _PATH_WUTMP_VER
 
 /* Provide trailing slash, since mostly used for building pathnames. */
 #define	_PATH_DEV	"/dev/"
diff --git a/sysdeps/generic/utmp-compat.h b/sysdeps/generic/utmp-compat.h
new file mode 100644
index 0000000000..122fd8905d
--- /dev/null
+++ b/sysdeps/generic/utmp-compat.h
@@ -0,0 +1,3 @@
+/* This macro defines the glibc version tag at which the 64 bit struct
+   utmp functions have been added to the 32 bit glibc.  */
+#define UTMP_COMPAT_BASE GLIBC_2_33
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index b4e39285d0..a9bbb5028d 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2196,12 +2196,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/mach/hurd/i386/libutil.abilist b/sysdeps/mach/hurd/i386/libutil.abilist
index 1dd59e0afb..6d97d3cd5e 100644
--- a/sysdeps/mach/hurd/i386/libutil.abilist
+++ b/sysdeps/mach/hurd/i386/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.2.6 login_tty F
 GLIBC_2.2.6 logout F
 GLIBC_2.2.6 logwtmp F
 GLIBC_2.2.6 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 54b707b9cc..9172a3347e 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2164,9 +2164,24 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libutil.abilist b/sysdeps/unix/sysv/linux/aarch64/libutil.abilist
index 99889de22e..3c2d9a1c14 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.17 login_tty F
 GLIBC_2.17 logout F
 GLIBC_2.17 logwtmp F
 GLIBC_2.17 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 9b429fd28f..bd217cb2c2 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2246,12 +2246,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/alpha/libutil.abilist b/sysdeps/unix/sysv/linux/alpha/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/alpha/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index 7ed5340364..898fd755ea 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -1924,9 +1924,24 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/arc/libutil.abilist b/sysdeps/unix/sysv/linux/arc/libutil.abilist
index 61f73bc34e..ea3c23b433 100644
--- a/sysdeps/unix/sysv/linux/arc/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.32 login_tty F
 GLIBC_2.32 logout F
 GLIBC_2.32 logwtmp F
 GLIBC_2.32 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index 3ec1cbdfbc..dd52296951 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -145,12 +145,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/arm/le/libutil.abilist b/sysdeps/unix/sysv/linux/arm/le/libutil.abilist
index cc1420e68c..ea54d58739 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libutil.abilist
@@ -1,3 +1,4 @@
+GLIBC_2.33 login F
 GLIBC_2.4 forkpty F
 GLIBC_2.4 login F
 GLIBC_2.4 login_tty F
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 301fd728d7..02636a8fa2 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2108,9 +2108,24 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/csky/libutil.abilist b/sysdeps/unix/sysv/linux/csky/libutil.abilist
index cbd11999a4..165b86bcf8 100644
--- a/sysdeps/unix/sysv/linux/csky/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.29 login_tty F
 GLIBC_2.29 logout F
 GLIBC_2.29 logwtmp F
 GLIBC_2.29 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 84834052e1..21912899a1 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2067,12 +2067,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/hppa/libutil.abilist b/sysdeps/unix/sysv/linux/hppa/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/hppa/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index b82debaba4..77b0d47f2a 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2233,12 +2233,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/i386/libutil.abilist b/sysdeps/unix/sysv/linux/i386/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/i386/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 475b7af1a5..7c84d98fcb 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2099,12 +2099,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/ia64/libutil.abilist b/sysdeps/unix/sysv/linux/ia64/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/ia64/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 29127e1341..421a82107f 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2179,12 +2179,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libutil.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index e5b4cecacd..6ae7a8f5ba 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2159,9 +2159,24 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libutil.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libutil.abilist
index 0da0a40c22..2f16f5498a 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.18 login_tty F
 GLIBC_2.18 logout F
 GLIBC_2.18 logwtmp F
 GLIBC_2.18 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index b9f56007a2..817b22b428 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2150,12 +2150,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libutil.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libutil.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index c161ef11b5..22772a572a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2156,12 +2156,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index d4b1528e7a..310db16538 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2150,12 +2150,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 68fca4e650..ba11176736 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2197,9 +2197,24 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/nios2/libutil.abilist b/sysdeps/unix/sysv/linux/nios2/libutil.abilist
index 19608bd74d..348b707eee 100644
--- a/sysdeps/unix/sysv/linux/nios2/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.21 login_tty F
 GLIBC_2.21 logout F
 GLIBC_2.21 logwtmp F
 GLIBC_2.21 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/paths.h b/sysdeps/unix/sysv/linux/paths.h
index 3b8aeab788..89686bcf88 100644
--- a/sysdeps/unix/sysv/linux/paths.h
+++ b/sysdeps/unix/sysv/linux/paths.h
@@ -62,10 +62,11 @@
 #define	_PATH_TTY	"/dev/tty"
 #define	_PATH_UNIX	"/boot/vmlinux"
 #define	_PATH_UTMP_BASE	"/var/run/utmp"
-#define	_PATH_UTMP	_PATH_UTMP_BASE
+#define	_PATH_UWTMP_VER	".v2"
+#define	_PATH_UTMP	_PATH_UTMP_BASE _PATH_UWTMP_VER
 #define	_PATH_VI	"/usr/bin/vi"
 #define	_PATH_WTMP_BASE	"/var/log/wtmp"
-#define	_PATH_WTMP	_PATH_WTMP_BASE
+#define	_PATH_WTMP	_PATH_WTMP_BASE _PATH_UWTMP_VER
 
 /* Provide trailing slash, since mostly used for building pathnames. */
 #define	_PATH_DEV	"/dev/"
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index bec34b2128..c599b985d1 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2206,12 +2206,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libutil.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index 35bd161c79..3362f3f6bb 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2069,12 +2069,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libutil.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libutil.abilist
index 9cf1da7aa4..41e5bf4a1f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.3 login_tty F
 GLIBC_2.3 logout F
 GLIBC_2.3 logwtmp F
 GLIBC_2.3 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index f1c8ad9cc5..aca57d0f38 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2359,9 +2359,24 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libutil.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libutil.abilist
index 99889de22e..3c2d9a1c14 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.17 login_tty F
 GLIBC_2.17 logout F
 GLIBC_2.17 logwtmp F
 GLIBC_2.17 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index fdfc373871..d4e6f75078 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2126,9 +2126,24 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libutil.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libutil.abilist
index cbfec8d46e..d9752a1da2 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.27 login_tty F
 GLIBC_2.27 logout F
 GLIBC_2.27 logwtmp F
 GLIBC_2.27 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutent_r.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutent_r.c
deleted file mode 100644
index 29d8c6a6f9..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutent_r.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <libc-lock.h>
-#include <stdlib.h>
-#include <utmp.h>
-
-#include "utmp-compat.h"
-#include "utmp-private.h"
-
-#if defined SHARED
-weak_alias (__setutent, setutent)
-weak_alias (__endutent, endutent)
-
-# undef weak_alias
-# define weak_alias(n,a)
-#endif
-#include "login/getutent_r.c"
-
-#if defined SHARED
-default_symbol_version (__getutent_r, getutent_r, UTMP_COMPAT_BASE);
-default_symbol_version (__pututline, pututline, UTMP_COMPAT_BASE);
-#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutid.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutid.c
deleted file mode 100644
index d3c63664df..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutid.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <stdlib.h>
-#include <utmp.h>
-
-#include "utmp-compat.h"
-
-#if defined SHARED
-# undef weak_alias
-# define weak_alias(n,a)
-#endif
-#include "login/getutid.c"
-
-#if defined SHARED
-default_symbol_version (__getutid, getutid, UTMP_COMPAT_BASE);
-#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutid_r.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutid_r.c
deleted file mode 100644
index e5511d406a..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutid_r.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <libc-lock.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <utmp.h>
-
-#include "utmp-compat.h"
-#include "utmp-private.h"
-
-#if defined SHARED
-# undef weak_alias
-# define weak_alias(n,a)
-#endif
-#include "login/getutid_r.c"
-
-#if defined SHARED
-default_symbol_version (__getutid_r, getutid_r, UTMP_COMPAT_BASE);
-#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutline.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutline.c
deleted file mode 100644
index 1c98cc5bba..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutline.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <stdlib.h>
-#include <utmp.h>
-
-#include "utmp-compat.h"
-
-#if defined SHARED
-# undef weak_alias
-# define weak_alias(n,a)
-#endif
-#include "login/getutline.c"
-
-#if defined SHARED
-default_symbol_version (__getutline, getutline, UTMP_COMPAT_BASE);
-#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutline_r.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutline_r.c
deleted file mode 100644
index f8b63342b4..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutline_r.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <errno.h>
-#include <libc-lock.h>
-#include <utmp.h>
-
-#include "utmp-compat.h"
-#include "utmp-private.h"
-
-#if defined SHARED
-# undef weak_alias
-# define weak_alias(n,a)
-#endif
-#include "login/getutline_r.c"
-
-#if defined SHARED
-default_symbol_version (__getutline_r, getutline_r, UTMP_COMPAT_BASE);;
-#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutmp.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutmp.c
deleted file mode 100644
index 50ce8c4f5c..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutmp.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#undef weak_alias
-#define weak_alias(a, b)
-#undef strong_alias
-#define strong_alias(a, b)
-
-#include <login/getutmp.c>
-
-#include "utmp-compat.h"
-
-default_symbol_version (__getutmp, getutmp, UTMP_COMPAT_BASE);
-_strong_alias (__getutmp, __getutmpx)
-default_symbol_version (__getutmpx, getutmpx, UTMP_COMPAT_BASE);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutxent.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutxent.c
deleted file mode 100644
index be887a672b..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutxent.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <utmp.h>
-#include <utmpx.h>
-
-#include "utmp-compat.h"
-
-#undef weak_alias
-#define weak_alias(n,a)
-#define getutxent __getutxent
-#include "login/getutxent.c"
-#undef getutxent
-
-default_symbol_version (__getutxent, getutxent, UTMP_COMPAT_BASE);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutxid.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutxid.c
deleted file mode 100644
index 85febe277b..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutxid.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <utmp.h>
-#include <utmpx.h>
-
-#include "utmp-compat.h"
-
-#undef weak_alias
-#define weak_alias(n,a)
-#define getutxid __getutxid
-#include "login/getutxid.c"
-#undef getutxid
-
-default_symbol_version (__getutxid, getutxid, UTMP_COMPAT_BASE);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutxline.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutxline.c
deleted file mode 100644
index a69740a712..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutxline.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <utmp.h>
-#include <utmpx.h>
-
-#include "utmp-compat.h"
-
-#undef weak_alias
-#define weak_alias(n,a)
-#define getutxline __getutxline
-#include "login/getutxline.c"
-#undef getutxline
-
-default_symbol_version (__getutxline, getutxline, UTMP_COMPAT_BASE);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/login.c b/sysdeps/unix/sysv/linux/s390/s390-32/login.c
deleted file mode 100644
index 25ee4a8b16..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/login.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <utmp.h>
-
-#include "utmp-compat.h"
-
-#undef weak_alias
-#define weak_alias(n,a)
-#define login __login
-#include "login/login.c"
-#undef login
-
-default_symbol_version (__login, login, UTMP_COMPAT_BASE);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/pututxline.c b/sysdeps/unix/sysv/linux/s390/s390-32/pututxline.c
deleted file mode 100644
index c8f773d9dc..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/pututxline.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <utmp.h>
-#include <utmpx.h>
-
-#include "utmp-compat.h"
-
-#undef weak_alias
-#define weak_alias(n,a)
-#define pututxline __pututxline
-#include "login/pututxline.c"
-#undef pututxline
-
-default_symbol_version (__pututxline, pututxline, UTMP_COMPAT_BASE);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/updwtmp.c b/sysdeps/unix/sysv/linux/s390/s390-32/updwtmp.c
deleted file mode 100644
index 2079571cc1..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/updwtmp.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <utmp.h>
-
-#include "utmp-compat.h"
-#include "utmp-private.h"
-
-#if defined SHARED
-# undef weak_alias
-# define weak_alias(n,a)
-#endif
-#include <login/updwtmp.c>
-
-#if defined SHARED
-default_symbol_version (__updwtmp, updwtmp, UTMP_COMPAT_BASE);
-#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/updwtmpx.c b/sysdeps/unix/sysv/linux/s390/s390-32/updwtmpx.c
deleted file mode 100644
index ce94139c3c..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/updwtmpx.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <utmp.h>
-#include <utmpx.h>
-
-#include "utmp-compat.h"
-
-#undef weak_alias
-#define weak_alias(n,a)
-#define updwtmpx __updwtmpx
-#include "login/updwtmpx.c"
-#undef updwtmpx
-
-default_symbol_version (__updwtmpx, updwtmpx, UTMP_COMPAT_BASE);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/utmp-compat.h b/sysdeps/unix/sysv/linux/s390/s390-32/utmp-compat.h
index 4e5972b65d..ef8115370c 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmp-compat.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/utmp-compat.h
@@ -18,4 +18,4 @@
 
 /* This macro defines the glibc version tag at which the 64 bit struct
    utmp functions have been added to the 32 bit glibc.  */
-#define UTMP_COMPAT_BASE GLIBC_2.9
+#define UTMP_COMPAT_BASE GLIBC_2_9
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/utmp32.c b/sysdeps/unix/sysv/linux/s390/s390-32/utmp32.c
deleted file mode 100644
index e4b82512f6..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmp32.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <sys/types.h>
-#include <utmp.h>
-#include <errno.h>
-#include <libc-symbols.h>
-
-#include "utmp32.h"
-#include "utmp-convert.h"
-
-/* Allocate a static buffer to be returned to the caller.  As well as
-   with the existing version of these functions the caller has to be
-   aware that the contents of this buffer will change with subsequent
-   calls.  */
-#define ALLOCATE_UTMP32_OUT(OUT)			\
-  static struct utmp32 *OUT = NULL;			\
-							\
-  if (OUT == NULL)					\
-    {							\
-      OUT = malloc (sizeof (struct utmp32));		\
-      if (OUT == NULL)					\
-	return NULL;					\
-    }
-
-/* Perform a lookup for a utmp entry matching FIELD using function
-   FUNC.  FIELD is converted to a 64 bit utmp and the result is
-   converted back to 32 bit utmp.  */
-#define ACCESS_UTMP_ENTRY(FUNC, FIELD)			\
-  struct utmp in64;					\
-  struct utmp *out64;					\
-  ALLOCATE_UTMP32_OUT (out32);				\
-							\
-  utmp_convert32to64 (FIELD, &in64);			\
-  out64 = FUNC (&in64);					\
-							\
-  if (out64 == NULL)					\
-    return NULL;					\
-							\
-  utmp_convert64to32 (out64, out32);			\
-							\
-  return out32;
-
-/* Search forward from the current point in the utmp file until the
-   next entry with a ut_type matching ID->ut_type.  */
-struct utmp32 *
-getutid32 (const struct utmp32 *id)
-{
-  ACCESS_UTMP_ENTRY (__getutid, id)
-}
-symbol_version (getutid32, getutid, GLIBC_2.0);
-
-/* Search forward from the current point in the utmp file until the
-   next entry with a ut_line matching LINE->ut_line.  */
-struct utmp32 *
-getutline32 (const struct utmp32 *line)
-{
-  ACCESS_UTMP_ENTRY (__getutline, line)
-}
-symbol_version (getutline32, getutline, GLIBC_2.0);
-
-/* Write out entry pointed to by UTMP_PTR into the utmp file.  */
-struct utmp32 *
-pututline32 (const struct utmp32 *utmp_ptr)
-{
-  ACCESS_UTMP_ENTRY (__pututline, utmp_ptr)
-}
-symbol_version (pututline32, pututline, GLIBC_2.0);
-
-/* Read next entry from a utmp-like file.  */
-struct utmp32 *
-getutent32 (void)
-{
-  struct utmp *out64;
-  ALLOCATE_UTMP32_OUT (out32);
-
-  out64 = __getutent ();
-  if (!out64)
-    return NULL;
-
-  utmp_convert64to32 (out64, out32);
-  return out32;
-}
-symbol_version (getutent32, getutent, GLIBC_2.0);
-
-/* Reentrant versions of the file for handling utmp files.  */
-
-int
-getutent32_r (struct utmp32 *buffer, struct utmp32 **result)
-{
-  struct utmp out64;
-  struct utmp *out64p;
-  int ret;
-
-  ret = __getutent_r (&out64, &out64p);
-  if (ret == -1)
-    {
-      *result = NULL;
-      return -1;
-    }
-
-  utmp_convert64to32 (out64p, buffer);
-  *result = buffer;
-
-  return 0;
-}
-symbol_version (getutent32_r, getutent_r, GLIBC_2.0);
-
-int
-getutid32_r (const struct utmp32 *id, struct utmp32 *buffer,
-	       struct utmp32 **result)
-{
-  struct utmp in64;
-  struct utmp out64;
-  struct utmp *out64p;
-  int ret;
-
-  utmp_convert32to64 (id, &in64);
-
-  ret = __getutid_r (&in64, &out64, &out64p);
-  if (ret == -1)
-    {
-      *result = NULL;
-      return -1;
-    }
-
-  utmp_convert64to32 (out64p, buffer);
-  *result = buffer;
-
-  return 0;
-}
-symbol_version (getutid32_r, getutid_r, GLIBC_2.0);
-
-int
-getutline32_r (const struct utmp32 *line,
-		 struct utmp32 *buffer, struct utmp32 **result)
-{
-  struct utmp in64;
-  struct utmp out64;
-  struct utmp *out64p;
-  int ret;
-
-  utmp_convert32to64 (line, &in64);
-
-  ret = __getutline_r (&in64, &out64, &out64p);
-  if (ret == -1)
-    {
-      *result = NULL;
-      return -1;
-    }
-
-  utmp_convert64to32 (out64p, buffer);
-  *result = buffer;
-
-  return 0;
-
-}
-symbol_version (getutline32_r, getutline_r, GLIBC_2.0);
-
-/* Append entry UTMP to the wtmp-like file WTMP_FILE.  */
-void
-updwtmp32 (const char *wtmp_file, const struct utmp32 *utmp)
-{
-  struct utmp in32;
-
-  utmp_convert32to64 (utmp, &in32);
-  __updwtmp (wtmp_file, &in32);
-}
-symbol_version (updwtmp32, updwtmp, GLIBC_2.0);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/utmpx-convert.h b/sysdeps/unix/sysv/linux/s390/s390-32/utmpx-convert.h
deleted file mode 100644
index 8d9bde559f..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmpx-convert.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-
-/* This file provides functions converting between the 32 and 64 bit
-   struct utmp variants.  */
-
-#ifndef _UTMPX_CONVERT_H
-#define _UTMPX_CONVERT_H 1
-
-#include <string.h>
-#include "utmpx32.h"
-
-/* Convert the 64 bit struct utmpx value in FROM to the 32 bit version
-   returned in TO.  */
-static inline void
-utmpx_convert64to32 (const struct utmpx *from, struct utmpx32 *to)
-{
-#if _HAVE_UT_TYPE - 0
-  to->ut_type = from->ut_type;
-#endif
-#if _HAVE_UT_PID - 0
-  to->ut_pid = from->ut_pid;
-#endif
-  memcpy (to->ut_line, from->ut_line, __UT_LINESIZE);
-  memcpy (to->ut_user, from->ut_user, __UT_NAMESIZE);
-#if _HAVE_UT_ID - 0
-  memcpy (to->ut_id, from->ut_id, 4);
-#endif
-#if _HAVE_UT_HOST - 0
-  memcpy (to->ut_host, from->ut_host, __UT_HOSTSIZE);
-#endif
-  to->ut_exit = from->ut_exit;
-  to->ut_session = (int32_t) from->ut_session;
-#if _HAVE_UT_TV - 0
-  to->ut_tv.tv_sec = (int32_t) from->ut_tv.tv_sec;
-  to->ut_tv.tv_usec = (int32_t) from->ut_tv.tv_usec;
-#endif
-  memcpy (to->ut_addr_v6, from->ut_addr_v6, 4 * 4);
-}
-
-/* Convert the 32 bit struct utmpx value in FROM to the 64 bit version
-   returned in TO.  */
-static inline void
-utmpx_convert32to64 (const struct utmpx32 *from, struct utmpx *to)
-{
-#if _HAVE_UT_TYPE - 0
-  to->ut_type = from->ut_type;
-#endif
-#if _HAVE_UT_PID - 0
-  to->ut_pid = from->ut_pid;
-#endif
-  memcpy (to->ut_line, from->ut_line, __UT_LINESIZE);
-  memcpy (to->ut_user, from->ut_user, __UT_NAMESIZE);
-#if _HAVE_UT_ID - 0
-  memcpy (to->ut_id, from->ut_id, 4);
-#endif
-#if _HAVE_UT_HOST - 0
-  memcpy (to->ut_host, from->ut_host, __UT_HOSTSIZE);
-#endif
-  to->ut_exit = from->ut_exit;
-  to->ut_session = (int64_t) from->ut_session;
-#if _HAVE_UT_TV - 0
-  to->ut_tv.tv_sec = (int64_t) from->ut_tv.tv_sec;
-  to->ut_tv.tv_usec = (int64_t) from->ut_tv.tv_usec;
-#endif
-  memcpy (to->ut_addr_v6, from->ut_addr_v6, 4 * 4);
-}
-
-#endif /* utmpx-convert.h */
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/utmpx32.c b/sysdeps/unix/sysv/linux/s390/s390-32/utmpx32.c
deleted file mode 100644
index 3f78fa62db..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmpx32.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* Copyright (C) 2008-2020 Free Software Foundation, Inc.
-   Contributed by Andreas Krebbel <Andreas.Krebbel@de.ibm.com>.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <sys/types.h>
-#include <utmp.h>
-#include <errno.h>
-#include <libc-symbols.h>
-
-#include "utmp32.h"
-#include "utmp-convert.h"
-
-#include "utmpx32.h"
-#include "utmpx-convert.h"
-
-/* Allocate a static buffer to be returned to the caller.  As well as
-   with the existing version of these functions the caller has to be
-   aware that the contents of this buffer will change with subsequent
-   calls.  */
-#define ALLOCATE_UTMPX32_OUT(OUT)			\
-  static struct utmpx32 *OUT = NULL;			\
-							\
-  if (OUT == NULL)					\
-    {							\
-      OUT = malloc (sizeof (struct utmpx32));		\
-      if (OUT == NULL)					\
-	return NULL;					\
-    }
-
-/* Perform a lookup for a utmpx entry matching FIELD using function
-   FUNC.  FIELD is converted to a 64 bit utmpx and the result is
-   converted back to 32 bit utmpx.  */
-#define ACCESS_UTMPX_ENTRY(FUNC, FIELD)			\
-  struct utmpx in64;					\
-  struct utmpx *out64;					\
-  ALLOCATE_UTMPX32_OUT (out32);				\
-							\
-  utmpx_convert32to64 (FIELD, &in64);			\
-  out64 = FUNC (&in64);					\
-							\
-  if (out64 == NULL)					\
-    return NULL;					\
-							\
-  utmpx_convert64to32 (out64, out32);			\
-							\
-  return out32;
-
-
-/* Get the next entry from the user accounting database.  */
-struct utmpx32 *
-getutxent32 (void)
-{
-  struct utmpx *out64;
-  ALLOCATE_UTMPX32_OUT (out32);
-
-  out64 = __getutxent ();
-  if (!out64)
-    return NULL;
-
-  utmpx_convert64to32 (out64, out32);
-  return out32;
-
-}
-symbol_version (getutxent32, getutxent, GLIBC_2.1);
-
-/* Get the user accounting database entry corresponding to ID.  */
-struct utmpx32 *
-getutxid32 (const struct utmpx32 *id)
-{
-  ACCESS_UTMPX_ENTRY (__getutxid, id);
-}
-symbol_version (getutxid32, getutxid, GLIBC_2.1);
-
-/* Get the user accounting database entry corresponding to LINE.  */
-struct utmpx32 *
-getutxline32 (const struct utmpx32 *line)
-{
-  ACCESS_UTMPX_ENTRY (__getutxline, line);
-}
-symbol_version (getutxline32, getutxline, GLIBC_2.1);
-
-/* Write the entry UTMPX into the user accounting database.  */
-struct utmpx32 *
-pututxline32 (const struct utmpx32 *utmpx)
-{
-  ACCESS_UTMPX_ENTRY (__pututxline, utmpx);
-}
-symbol_version (pututxline32, pututxline, GLIBC_2.1);
-
-/* Append entry UTMP to the wtmpx-like file WTMPX_FILE.  */
-void
-updwtmpx32 (const char *wtmpx_file, const struct utmpx32 *utmpx)
-{
-  struct utmpx in64;
-
-  utmpx_convert32to64 (utmpx, &in64);
-  __updwtmpx (wtmpx_file, &in64);
-}
-symbol_version (updwtmpx32, updwtmpx, GLIBC_2.1);
-
-/* Copy the information in UTMPX to UTMP.  */
-void
-getutmp32 (const struct utmpx32 *utmpx, struct utmp32 *utmp)
-{
-  struct utmpx in64;
-  struct utmp out64;
-
-  utmpx_convert32to64 (utmpx, &in64);
-  __getutmp (&in64, &out64);
-  utmp_convert64to32 (&out64, utmp);
-}
-symbol_version (getutmp32, getutmp, GLIBC_2.1.1);
-
-/* Copy the information in UTMP to UTMPX.  */
-void
-getutmpx32 (const struct utmp32 *utmp, struct utmpx32 *utmpx)
-{
-  struct utmp in64;
-  struct utmpx out64;
-
-  utmp_convert32to64 (utmp, &in64);
-  __getutmpx (&in64, &out64);
-  utmpx_convert64to32 (&out64, utmpx);
-}
-symbol_version (getutmpx32, getutmpx, GLIBC_2.1.1);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/utmp-compat.h b/sysdeps/unix/sysv/linux/s390/s390-64/utmp-compat.h
new file mode 100644
index 0000000000..fee4b80cc0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/utmp-compat.h
@@ -0,0 +1,3 @@
+/* s390x already has 64-bit time for struct utmp{x} and lastlog.  This define
+   disable the compat symbols and support to 32-bit entries.  */
+#define UTMP_COMPAT_BASE GLIBC_2_0
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index b4cebb11dd..ea78226332 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2071,12 +2071,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libutil.abilist b/sysdeps/unix/sysv/linux/sh/le/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index f208405859..6f3a2df230 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2195,12 +2195,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libutil.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 44e68aded2..b4e75bb47e 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2122,12 +2122,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libutil.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libutil.abilist
index aa2d35b323..1bd22adb45 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.0 login_tty F
 GLIBC_2.0 logout F
 GLIBC_2.0 logwtmp F
 GLIBC_2.0 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/utmp-path.h b/sysdeps/unix/sysv/linux/utmp-path.h
index a377bc9dba..f42638e2c5 100644
--- a/sysdeps/unix/sysv/linux/utmp-path.h
+++ b/sysdeps/unix/sysv/linux/utmp-path.h
@@ -19,9 +19,8 @@
 #ifndef _UTMP_PATH_H
 #define _UTMP_PATH_H 1
 
-#include <string.h>
 #include <unistd.h>
-
+#include <string.h>
 
 /* The function returns the utmp database for 32-bit utmp{x} entries based
    on FILE_NAME:
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 51e76861f6..74c0c26ba5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2080,12 +2080,27 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libutil.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libutil.abilist
index 1356ed4115..7df76778a4 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.2.5 login_tty F
 GLIBC_2.2.5 logout F
 GLIBC_2.2.5 logwtmp F
 GLIBC_2.2.5 openpty F
+GLIBC_2.33 login F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index f83473c11f..3597a3ff88 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2177,9 +2177,24 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 getutent F
+GLIBC_2.33 getutent_r F
+GLIBC_2.33 getutid F
+GLIBC_2.33 getutid_r F
+GLIBC_2.33 getutline F
+GLIBC_2.33 getutline_r F
+GLIBC_2.33 getutmp F
+GLIBC_2.33 getutmpx F
+GLIBC_2.33 getutxent F
+GLIBC_2.33 getutxid F
+GLIBC_2.33 getutxline F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
 GLIBC_2.33 mknodat F
+GLIBC_2.33 pututline F
+GLIBC_2.33 pututxline F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
+GLIBC_2.33 updwtmp F
+GLIBC_2.33 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libutil.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libutil.abilist
index cff23106f5..9431f297d8 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.16 login_tty F
 GLIBC_2.16 logout F
 GLIBC_2.16 logwtmp F
 GLIBC_2.16 openpty F
+GLIBC_2.33 login F
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 5/7] linux: Add pwrite64_nocancel
  2020-08-05 18:59 [PATCH v2 1/7] login: Move gnu utmpx to default implementation Adhemerval Zanella via Libc-alpha
                   ` (2 preceding siblings ...)
  2020-08-05 18:59 ` [PATCH v2 4/7] login: Add 64-bit time support to utmp/utmpx Adhemerval Zanella via Libc-alpha
@ 2020-08-05 18:59 ` Adhemerval Zanella via Libc-alpha
  2020-08-05 18:59 ` [PATCH v2 6/7] login: Use 64-bit time on struct lastlog Adhemerval Zanella via Libc-alpha
  2020-08-05 18:59 ` [PATCH v2 7/7] Remove __WORDSIZE_TIME64_COMPAT32 Adhemerval Zanella via Libc-alpha
  5 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 18:59 UTC (permalink / raw)
  To: libc-alpha

It is not used internally yet.
---
 sysdeps/unix/sysv/linux/Makefile            |  2 +-
 sysdeps/unix/sysv/linux/not-cancel.h        |  4 +++
 sysdeps/unix/sysv/linux/pwrite64_nocancel.c | 29 +++++++++++++++++++++
 3 files changed, 34 insertions(+), 1 deletion(-)
 create mode 100644 sysdeps/unix/sysv/linux/pwrite64_nocancel.c

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 39305c97e7..682f4af55d 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -273,7 +273,7 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \
 		   close_nocancel fcntl_nocancel \
 		   open_nocancel open64_nocancel \
 		   openat_nocancel openat64_nocancel \
-		   read_nocancel pread64_nocancel \
+		   read_nocancel pread64_nocancel pwrite64_nocancel \
 		   write_nocancel statx_cp stat_t64_cp
 
 sysdep_headers += bits/fcntl-linux.h
diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h
index bf09a3d6b8..d2e46be35b 100644
--- a/sysdeps/unix/sysv/linux/not-cancel.h
+++ b/sysdeps/unix/sysv/linux/not-cancel.h
@@ -46,6 +46,9 @@ __typeof (__read) __read_nocancel;
 /* Non cancellable pread syscall (LFS version).  */
 __typeof (__pread64) __pread64_nocancel;
 
+/* Non cancellable pwrite syscall (LFS version).  */
+__typeof (__pwrite64) __pwrite64_nocancel;
+
 /* Uncancelable write.  */
 __typeof (__write) __write_nocancel;
 
@@ -78,6 +81,7 @@ hidden_proto (__openat_nocancel)
 hidden_proto (__openat64_nocancel)
 hidden_proto (__read_nocancel)
 hidden_proto (__pread64_nocancel)
+hidden_proto (__pwrite64_nocancel)
 hidden_proto (__write_nocancel)
 hidden_proto (__close_nocancel)
 hidden_proto (__fcntl64_nocancel)
diff --git a/sysdeps/unix/sysv/linux/pwrite64_nocancel.c b/sysdeps/unix/sysv/linux/pwrite64_nocancel.c
new file mode 100644
index 0000000000..06d0ae14d0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/pwrite64_nocancel.c
@@ -0,0 +1,29 @@
+/* Linux pwrite64() syscall implementation -- non-cancellable.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+ssize_t
+__pwrite64_nocancel (int fd, const void *buf, size_t count, off64_t offset)
+{
+  return INLINE_SYSCALL_CALL (pwrite64, fd, buf, count,
+			      SYSCALL_LL64_PRW (offset));
+}
+hidden_def (__pwrite64_nocancel)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 6/7] login: Use 64-bit time on struct lastlog
  2020-08-05 18:59 [PATCH v2 1/7] login: Move gnu utmpx to default implementation Adhemerval Zanella via Libc-alpha
                   ` (3 preceding siblings ...)
  2020-08-05 18:59 ` [PATCH v2 5/7] linux: Add pwrite64_nocancel Adhemerval Zanella via Libc-alpha
@ 2020-08-05 18:59 ` Adhemerval Zanella via Libc-alpha
  2020-08-05 19:56   ` Florian Weimer
  2020-08-05 18:59 ` [PATCH v2 7/7] Remove __WORDSIZE_TIME64_COMPAT32 Adhemerval Zanella via Libc-alpha
  5 siblings, 1 reply; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 18:59 UTC (permalink / raw)
  To: libc-alpha

The new struct has the same size on both 32-bit and 64-bit
architectures.  As for utmp{x} 64-bit time_t support, a new file name
is defined for _PATH_LASTLOG.

Also two new symbols are added that read/write 'struct lastlog'
entries, 'lastlog_read' and 'lastlog_write'.  Both are GNU extensions
and handle the 32-bit entry operation if the argument is the old
_PATH_LASTLOG path.

Different than utmp{x}, no concurrent access is done (such as
advisory locking).  I modeled these function on how program that
access lastlog file uses (such as shadow-utils and util-linux).

The s390 is the only architecture that already defined the
'struct lastlog' with 64-bit time_t and to handle s390 has a specific
lastlog-compat.h header where 'is_path_lastlog_compat' already
return false (thus making both lastlog_read and lastlog_write
always read/write registers with 64-bit ll_time).

It also fixes BZ#25844 by adding the __attribute_nonstring__ on
ll_line and ll_host.

Checked on x86_64-linux-gnu and i686-linux-gnu.
---
 bits/types/struct_lastlog.h                   |  8 +-
 login/Makefile                                |  5 +-
 login/Versions                                |  3 +
 .../lastlog-compat.h                          | 27 ++++---
 login/lastlog_read.c                          | 71 +++++++++++++++++
 login/lastlog_write.c                         | 59 ++++++++++++++
 login/tst-lastlog.c                           | 79 +++++++++++++++++++
 login/tst-lastlog.root/tst-lastlog.script     |  6 ++
 login/utmp.h                                  | 11 +++
 sysdeps/generic/paths.h                       |  3 +-
 sysdeps/mach/hurd/i386/libc.abilist           |  2 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |  2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |  2 +
 sysdeps/unix/sysv/linux/arc/libc.abilist      |  2 +
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |  2 +
 sysdeps/unix/sysv/linux/csky/libc.abilist     |  2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |  2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |  2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |  2 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |  2 +
 .../sysv/linux/microblaze/be/libc.abilist     |  2 +
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |  2 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |  2 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |  2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |  2 +
 sysdeps/unix/sysv/linux/paths.h               |  3 +-
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |  2 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |  2 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |  2 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |  2 +
 sysdeps/unix/sysv/linux/s390/lastlog-compat.h | 38 +++++++++
 .../unix/sysv/linux/s390/s390-32/libc.abilist |  2 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |  2 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |  2 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |  2 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |  2 +
 .../unix/sysv/linux/x86_64/64/libc.abilist    |  2 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |  2 +
 38 files changed, 345 insertions(+), 20 deletions(-)
 rename sysdeps/unix/sysv/linux/s390/bits/struct_lastlog.h => login/lastlog-compat.h (74%)
 create mode 100644 login/lastlog_read.c
 create mode 100644 login/lastlog_write.c
 create mode 100644 login/tst-lastlog.c
 create mode 100644 login/tst-lastlog.root/tst-lastlog.script
 create mode 100644 sysdeps/unix/sysv/linux/s390/lastlog-compat.h

diff --git a/bits/types/struct_lastlog.h b/bits/types/struct_lastlog.h
index 67ffec1b08..9e8983b57d 100644
--- a/bits/types/struct_lastlog.h
+++ b/bits/types/struct_lastlog.h
@@ -24,11 +24,11 @@
    previous logins.  */
 struct lastlog
 {
-#if __WORDSIZE_TIME64_COMPAT32
-  int32_t ll_time;
+#if __WORDSIZE == 32
+  int64_t ll_time;
 #else
   __time_t ll_time;
 #endif
-  char ll_line[UT_LINESIZE];
-  char ll_host[UT_HOSTSIZE];
+  char ll_line[UT_LINESIZE] __attribute_nonstring__;
+  char ll_host[UT_HOSTSIZE] __attribute_nonstring__;
 };
diff --git a/login/Makefile b/login/Makefile
index 848caa0c44..c072dfdf46 100644
--- a/login/Makefile
+++ b/login/Makefile
@@ -31,7 +31,8 @@ headers	:= utmp.h bits/utmp.h lastlog.h pty.h \
 routines := getlogin getlogin_r setlogin getlogin_r_chk \
 	    getutent getutent_r getutid getutline getutid_r getutline_r \
 	    utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname \
-	    ptsname_r_chk utmp32 utmpx32 utmp-convert
+	    ptsname_r_chk utmp32 utmpx32 utmp-convert \
+	    lastlog_read lastlog_write
 
 CFLAGS-grantpt.c += -DLIBEXECDIR='"$(libexecdir)"'
 
@@ -50,7 +51,7 @@ tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
   tst-pututxline-lockfail tst-pututxline-cache
 
 tests-internal := tst-utmp32
-tests-container := tst-utmp32 tst-utmp-default
+tests-container := tst-utmp32 tst-utmp-default tst-lastlog
 
 # Build the -lutil library with these extra functions.
 extra-libs      := libutil
diff --git a/login/Versions b/login/Versions
index 6c53d6639e..13da0d15fd 100644
--- a/login/Versions
+++ b/login/Versions
@@ -45,6 +45,9 @@ libc {
     __getlogin_r_chk;
     __ptsname_r_chk;
   }
+  GLIBC_2.33 {
+    lastlog_read; lastlog_write;
+  }
   GLIBC_PRIVATE {
     # Used on compat login from libutil.
     __utmp_convert32to64;
diff --git a/sysdeps/unix/sysv/linux/s390/bits/struct_lastlog.h b/login/lastlog-compat.h
similarity index 74%
rename from sysdeps/unix/sysv/linux/s390/bits/struct_lastlog.h
rename to login/lastlog-compat.h
index 1faa472ec8..687774a21e 100644
--- a/sysdeps/unix/sysv/linux/s390/bits/struct_lastlog.h
+++ b/login/lastlog-compat.h
@@ -1,4 +1,4 @@
-/* The 'struct lastlog' type.
+/* Compat lastlog definitions.
    Copyright (C) 2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -16,19 +16,22 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef _UTMP_H
-# error "Never include <bits/struct_lastlog.h> directly; use <utmp.h> instead."
-#endif
+#ifndef _LASTLOG_COMPAT_H
+#define _LASTLOG_COMPAT_H 1
+
+#include <string.h>
 
-/* The structure describing an entry in the database of
-   previous logins.  */
-struct lastlog
+struct lastlog_compat
 {
-#if __WORDSIZE == 32
-  int64_t ll_time;
-#else
-  __time_t ll_time;
-#endif
+  int32_t ll_time;
   char ll_line[UT_LINESIZE];
   char ll_host[UT_HOSTSIZE];
 };
+
+static inline bool
+is_path_lastlog_compat (const char *file)
+{
+  return strcmp (file, "/var/log/lastlog") == 0;
+}
+
+#endif
diff --git a/login/lastlog_read.c b/login/lastlog_read.c
new file mode 100644
index 0000000000..e2c6e82a15
--- /dev/null
+++ b/login/lastlog_read.c
@@ -0,0 +1,71 @@
+/* Read a lastlog entry.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <utmp.h>
+#include <stdbool.h>
+#include <not-cancel.h>
+#include <lastlog-compat.h>
+
+ssize_t
+lastlog_read (const char *file, uid_t uid, struct lastlog *ll)
+{
+  int fd = __open_nocancel (file, O_RDONLY | O_LARGEFILE | O_CLOEXEC);
+  if (fd == -1)
+    return -1;
+
+  size_t llsize;
+  struct lastlog_compat llcompat;
+  void *data;
+
+  if (is_path_lastlog_compat (file))
+    {
+      llsize = sizeof (struct lastlog_compat);
+      data = &llcompat;
+    }
+  else
+    {
+      llsize = sizeof (struct lastlog);
+      data = ll;
+    }
+
+  off64_t off = llsize * uid;
+  ssize_t r = __pread64_nocancel (fd, data, llsize, off);
+  __close_nocancel_nostatus (fd);
+
+  if (r == llsize && data == &llcompat)
+    {
+      ll->ll_time = llcompat.ll_time;
+      memcpy (ll->ll_line, llcompat.ll_line, UT_LINESIZE);
+      memcpy (ll->ll_host, llcompat.ll_host, UT_HOSTSIZE);
+    }
+
+  if (r == llsize)
+    {
+      if (data == &llcompat)
+	{
+	  ll->ll_time = llcompat.ll_time;
+	  memcpy (ll->ll_line, llcompat.ll_line, UT_LINESIZE);
+	  memcpy (ll->ll_host, llcompat.ll_host, UT_HOSTSIZE);
+	}
+      /* We need to return the expected 'struct lastlog' size in case of
+	 success.  */
+      r = sizeof (struct lastlog);
+    }
+
+  return r;
+}
diff --git a/login/lastlog_write.c b/login/lastlog_write.c
new file mode 100644
index 0000000000..f3aedcbdb7
--- /dev/null
+++ b/login/lastlog_write.c
@@ -0,0 +1,59 @@
+/* Write a lastlog entry.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <utmp.h>
+#include <stdbool.h>
+#include <not-cancel.h>
+#include <lastlog-compat.h>
+
+ssize_t
+lastlog_write (const char *file, uid_t uid, const struct lastlog *ll)
+{
+  int fd = __open_nocancel (file, O_WRONLY | O_LARGEFILE | O_CLOEXEC);
+  if (fd == -1)
+    return -1;
+
+  size_t llsize;
+  struct lastlog_compat llcompat;
+  const void *data;
+
+  if (is_path_lastlog_compat (file))
+    {
+      llcompat.ll_time = ll->ll_time;
+      memcpy (llcompat.ll_line, ll->ll_line, UT_LINESIZE);
+      memcpy (llcompat.ll_host, ll->ll_host, UT_HOSTSIZE);
+      llsize = sizeof (struct lastlog_compat);
+      data = &llcompat;
+    }
+  else
+    {
+      llsize = sizeof (struct lastlog);
+      data = ll;
+    }
+
+  off64_t off = llsize * uid;
+  ssize_t r = __pwrite64_nocancel (fd, data, llsize, off);
+  __close_nocancel_nostatus (fd);
+
+  /* We need to return the expected 'struct lastlog' size in case of
+     success.  */
+  if (r == llsize && data == &llcompat)
+    r = sizeof (struct lastlog);
+
+  return r;
+}
diff --git a/login/tst-lastlog.c b/login/tst-lastlog.c
new file mode 100644
index 0000000000..9376a6ddf4
--- /dev/null
+++ b/login/tst-lastlog.c
@@ -0,0 +1,79 @@
+/* Tests for lastlog read/write functions.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <string.h>
+#include <utmp.h>
+
+#include <support/check.h>
+#include <support/temp_file.h>
+
+#include <stdio.h>
+
+static struct
+{
+  uid_t uid;
+  struct lastlog ll;
+} entry[] =
+{
+  { 0,    { .ll_time = 1000, .ll_line = "tty1" } },
+  { 1000, { .ll_time = 2000, .ll_line = "pts/0", .ll_host = "127.0.0.1" } },
+  { 20,   { .ll_time = 3000, .ll_line = "pts/1", .ll_host = "192.168.0.1" } },
+  { 30,   { .ll_time = 4000, .ll_line = "tty2" } },
+};
+const size_t entry_size = sizeof (entry) / sizeof (entry[0]);
+
+static void
+run_test (const char *filename)
+{
+  for (int n = 0; n < entry_size; n++)
+    TEST_COMPARE (lastlog_write (filename, entry[n].uid, &entry[n].ll),
+		  sizeof (struct lastlog));
+
+  for (int n = 0; n < entry_size; n++)
+    {
+      struct lastlog ll;
+      TEST_COMPARE (lastlog_read (filename, entry[n].uid, &ll),
+		    sizeof (struct lastlog));
+      TEST_COMPARE (ll.ll_time, entry[n].ll.ll_time);
+      TEST_COMPARE_BLOB (ll.ll_line, UT_LINESIZE,
+			 entry[n].ll.ll_line, UT_LINESIZE);
+      TEST_COMPARE_BLOB (ll.ll_host, UT_HOSTSIZE,
+			 entry[n].ll.ll_host, UT_HOSTSIZE);
+    }
+
+  /* Check with an non present uid.  */
+  {
+    struct lastlog ll;
+    TEST_COMPARE (lastlog_read (filename, 4000, &ll), 0);
+  }
+}
+
+static int
+do_test (void)
+{
+  /* The path triggers the read/write of compat (32-bit ll_time) entries.  */
+  run_test ("/var/run/lastlog");
+
+  /* Any other file handles new (64-bit ll_time) entries.  */
+  run_test ("/var/run/lastlog.v2");
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/login/tst-lastlog.root/tst-lastlog.script b/login/tst-lastlog.root/tst-lastlog.script
new file mode 100644
index 0000000000..ca34ce7021
--- /dev/null
+++ b/login/tst-lastlog.root/tst-lastlog.script
@@ -0,0 +1,6 @@
+mkdirp 0755 /var/run
+touch  0664 /var/run/lastlog
+touch  0664 /var/run/lastlog.v2
+
+# Must run localedef as root to write into default paths.
+su
diff --git a/login/utmp.h b/login/utmp.h
index 3de2b8596b..23304016d1 100644
--- a/login/utmp.h
+++ b/login/utmp.h
@@ -91,6 +91,17 @@ extern int getutline_r (const struct utmp *__line,
 
 #endif	/* Use misc.  */
 
+#ifdef __USE_GNU
+/* Read the struct lastlog LL with UID from file FILE.  */
+extern ssize_t lastlog_read (const char *__file, uid_t __uid,
+			     struct lastlog *__ll)
+     __THROW __nonnull ((1, 3));
+/* Write the struct lastlog LL with UID from file FILE.  */
+extern ssize_t lastlog_write (const char *__file, uid_t __uid,
+			      const struct lastlog *__ll)
+     __THROW __nonnull ((1, 3));
+#endif
+
 __END_DECLS
 
 #endif /* utmp.h  */
diff --git a/sysdeps/generic/paths.h b/sysdeps/generic/paths.h
index ab2980e14a..9321ad7294 100644
--- a/sysdeps/generic/paths.h
+++ b/sysdeps/generic/paths.h
@@ -46,7 +46,8 @@
 #define	_PATH_DRUM	"/dev/drum"
 #define	_PATH_GSHADOW	"/etc/gshadow"
 #define	_PATH_KMEM	"/dev/kmem"
-#define	_PATH_LASTLOG	"/var/log/lastlog"
+#define _PATH_LASTLOG_VER ".v2"
+#define	_PATH_LASTLOG	"/var/log/lastlog" _PATH_LASTLOG_VER
 #define	_PATH_MAILDIR	"/var/mail"
 #define	_PATH_MAN	"/usr/share/man"
 #define	_PATH_MEM	"/dev/mem"
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index a9bbb5028d..e58dbc1176 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2207,6 +2207,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 9172a3347e..307e519508 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2175,6 +2175,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index bd217cb2c2..3b160667cb 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2257,6 +2257,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index 898fd755ea..e460316be2 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -1935,6 +1935,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index dd52296951..b4ecc0ebe2 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -156,6 +156,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 02636a8fa2..e663f473b5 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2119,6 +2119,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 21912899a1..0c7e306946 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2078,6 +2078,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 77b0d47f2a..7550213cda 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2244,6 +2244,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 7c84d98fcb..4ed0dc12cc 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2110,6 +2110,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 421a82107f..e1940b2af8 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2190,6 +2190,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index 6ae7a8f5ba..1bbd2eaa00 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2170,6 +2170,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 817b22b428..0dd1fb731e 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2161,6 +2161,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 22772a572a..740e322ee0 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2167,6 +2167,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 310db16538..b3d6cd7dbc 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2161,6 +2161,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index ba11176736..17dded8e1f 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2208,6 +2208,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/paths.h b/sysdeps/unix/sysv/linux/paths.h
index 89686bcf88..b78dff7ae3 100644
--- a/sysdeps/unix/sysv/linux/paths.h
+++ b/sysdeps/unix/sysv/linux/paths.h
@@ -47,7 +47,8 @@
 #define	_PATH_GSHADOW	"/etc/gshadow"
 #define	_PATH_KLOG	"/proc/kmsg"
 #define	_PATH_KMEM	"/dev/kmem"
-#define	_PATH_LASTLOG	"/var/log/lastlog"
+#define _PATH_LASTLOG_VER ".v2"
+#define	_PATH_LASTLOG	"/var/log/lastlog" _PATH_LASTLOG_VER
 #define	_PATH_MAILDIR	"/var/mail"
 #define	_PATH_MAN	"/usr/share/man"
 #define	_PATH_MEM	"/dev/mem"
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index c599b985d1..960a6364b9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2217,6 +2217,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index 3362f3f6bb..248569d295 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2080,6 +2080,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index aca57d0f38..d1c84dba37 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2370,6 +2370,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index d4e6f75078..ca89f2d719 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2137,6 +2137,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/s390/lastlog-compat.h b/sysdeps/unix/sysv/linux/s390/lastlog-compat.h
new file mode 100644
index 0000000000..56fadc3b3b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/lastlog-compat.h
@@ -0,0 +1,38 @@
+/* Compat lastlog definitions.  s390 definition.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _LASTLOG_COMPAT_H
+#define _LASTLOG_COMPAT_H 1
+
+/* The s390 changes its lastlog to 64-bit on glibc 2.9 without any handling
+   of old format.  The is_path_lastlog_compat assumes 64-bit as default.  */
+
+struct lastlog_compat
+{
+  int64_t ll_time;
+  char ll_line[UT_LINESIZE];
+  char ll_host[UT_HOSTSIZE];
+};
+
+static inline bool
+is_path_lastlog_compat (const char *file)
+{
+  return false;
+}
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 47591dc5b5..30c8837c0f 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2204,6 +2204,8 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index bd96aeaff7..09112747dd 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2105,6 +2105,8 @@ GLIBC_2.33 fstat F
 GLIBC_2.33 fstat64 F
 GLIBC_2.33 fstatat F
 GLIBC_2.33 fstatat64 F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index ea78226332..6f19690273 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2082,6 +2082,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 6f3a2df230..c00a11f68c 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2206,6 +2206,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index b4e75bb47e..af5b71b548 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2133,6 +2133,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 74c0c26ba5..34c53c17fe 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2091,6 +2091,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 3597a3ff88..bfd31c5944 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2188,6 +2188,8 @@ GLIBC_2.33 getutmpx F
 GLIBC_2.33 getutxent F
 GLIBC_2.33 getutxid F
 GLIBC_2.33 getutxline F
+GLIBC_2.33 lastlog_read F
+GLIBC_2.33 lastlog_write F
 GLIBC_2.33 lstat F
 GLIBC_2.33 lstat64 F
 GLIBC_2.33 mknod F
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 7/7] Remove __WORDSIZE_TIME64_COMPAT32
  2020-08-05 18:59 [PATCH v2 1/7] login: Move gnu utmpx to default implementation Adhemerval Zanella via Libc-alpha
                   ` (4 preceding siblings ...)
  2020-08-05 18:59 ` [PATCH v2 6/7] login: Use 64-bit time on struct lastlog Adhemerval Zanella via Libc-alpha
@ 2020-08-05 18:59 ` Adhemerval Zanella via Libc-alpha
  5 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 18:59 UTC (permalink / raw)
  To: libc-alpha

With 'struct utmpx', 'struct utmp', and 'struct lastlog' using
64-bit time unconditionally this macro is not used anymore.
---
 bits/wordsize.h                                 | 6 ------
 sysdeps/aarch64/bits/wordsize.h                 | 2 --
 sysdeps/mips/bits/wordsize.h                    | 6 ------
 sysdeps/powerpc/powerpc32/bits/wordsize.h       | 2 --
 sysdeps/powerpc/powerpc64/bits/wordsize.h       | 2 --
 sysdeps/riscv/bits/wordsize.h                   | 6 ------
 sysdeps/s390/s390-32/bits/wordsize.h            | 2 --
 sysdeps/s390/s390-64/bits/wordsize.h            | 2 --
 sysdeps/sparc/sparc32/bits/wordsize.h           | 2 --
 sysdeps/sparc/sparc64/bits/wordsize.h           | 2 --
 sysdeps/unix/sysv/linux/alpha/bits/wordsize.h   | 1 -
 sysdeps/unix/sysv/linux/powerpc/bits/wordsize.h | 2 --
 sysdeps/unix/sysv/linux/sparc/bits/wordsize.h   | 2 --
 sysdeps/wordsize-32/bits/wordsize.h             | 1 -
 sysdeps/wordsize-64/bits/wordsize.h             | 1 -
 sysdeps/x86/bits/wordsize.h                     | 3 ---
 16 files changed, 42 deletions(-)

diff --git a/bits/wordsize.h b/bits/wordsize.h
index 14edae3a11..e20fd2e4c2 100644
--- a/bits/wordsize.h
+++ b/bits/wordsize.h
@@ -19,9 +19,3 @@
    __WORDSIZE is 32 and ptrdiff_t is type 'int' and leave undefined if
    __WORDSIZE is 64.  */
 #define __WORDSIZE32_PTRDIFF_LONG
-
-/* Set to 1 in order to force time types to be 32 bits instead of 64 bits in
-   struct lastlog and struct utmp{,x} on 64-bit ports.  This may be done in
-   order to make 64-bit ports compatible with 32-bit ports.  Set to 0 for
-   64-bit ports where the time types are 64-bits or for any 32-bit ports.  */
-#define __WORDSIZE_TIME64_COMPAT32
diff --git a/sysdeps/aarch64/bits/wordsize.h b/sysdeps/aarch64/bits/wordsize.h
index ee01841773..adc083d662 100644
--- a/sysdeps/aarch64/bits/wordsize.h
+++ b/sysdeps/aarch64/bits/wordsize.h
@@ -24,5 +24,3 @@
 # define __WORDSIZE32_SIZE_ULONG	1
 # define __WORDSIZE32_PTRDIFF_LONG	1
 #endif
-
-#define __WORDSIZE_TIME64_COMPAT32	0
diff --git a/sysdeps/mips/bits/wordsize.h b/sysdeps/mips/bits/wordsize.h
index d14f497895..3af04daea6 100644
--- a/sysdeps/mips/bits/wordsize.h
+++ b/sysdeps/mips/bits/wordsize.h
@@ -19,12 +19,6 @@
 
 #define __WORDSIZE			_MIPS_SZPTR
 
-#if _MIPS_SIM == _ABI64
-# define __WORDSIZE_TIME64_COMPAT32	1
-#else
-# define __WORDSIZE_TIME64_COMPAT32	0
-#endif
-
 #if __WORDSIZE == 32
 #define __WORDSIZE32_SIZE_ULONG		0
 #define __WORDSIZE32_PTRDIFF_LONG	0
diff --git a/sysdeps/powerpc/powerpc32/bits/wordsize.h b/sysdeps/powerpc/powerpc32/bits/wordsize.h
index 04ca9debf0..df1aa27244 100644
--- a/sysdeps/powerpc/powerpc32/bits/wordsize.h
+++ b/sysdeps/powerpc/powerpc32/bits/wordsize.h
@@ -2,10 +2,8 @@
 
 #if defined __powerpc64__
 # define __WORDSIZE	64
-# define __WORDSIZE_TIME64_COMPAT32	1
 #else
 # define __WORDSIZE	32
-# define __WORDSIZE_TIME64_COMPAT32	0
 # define __WORDSIZE32_SIZE_ULONG	0
 # define __WORDSIZE32_PTRDIFF_LONG	0
 #endif
diff --git a/sysdeps/powerpc/powerpc64/bits/wordsize.h b/sysdeps/powerpc/powerpc64/bits/wordsize.h
index 04ca9debf0..df1aa27244 100644
--- a/sysdeps/powerpc/powerpc64/bits/wordsize.h
+++ b/sysdeps/powerpc/powerpc64/bits/wordsize.h
@@ -2,10 +2,8 @@
 
 #if defined __powerpc64__
 # define __WORDSIZE	64
-# define __WORDSIZE_TIME64_COMPAT32	1
 #else
 # define __WORDSIZE	32
-# define __WORDSIZE_TIME64_COMPAT32	0
 # define __WORDSIZE32_SIZE_ULONG	0
 # define __WORDSIZE32_PTRDIFF_LONG	0
 #endif
diff --git a/sysdeps/riscv/bits/wordsize.h b/sysdeps/riscv/bits/wordsize.h
index faccc71828..182e3d33a6 100644
--- a/sysdeps/riscv/bits/wordsize.h
+++ b/sysdeps/riscv/bits/wordsize.h
@@ -21,9 +21,3 @@
 #else
 # error unsupported ABI
 #endif
-
-#if __riscv_xlen == 64
-# define __WORDSIZE_TIME64_COMPAT32 1
-#else
-# error "rv32i-based targets are not supported"
-#endif
diff --git a/sysdeps/s390/s390-32/bits/wordsize.h b/sysdeps/s390/s390-32/bits/wordsize.h
index 129e47182b..755050861e 100644
--- a/sysdeps/s390/s390-32/bits/wordsize.h
+++ b/sysdeps/s390/s390-32/bits/wordsize.h
@@ -7,5 +7,3 @@
 # define __WORDSIZE32_SIZE_ULONG       1
 # define __WORDSIZE32_PTRDIFF_LONG      0
 #endif
-
-#define __WORDSIZE_TIME64_COMPAT32     0
diff --git a/sysdeps/s390/s390-64/bits/wordsize.h b/sysdeps/s390/s390-64/bits/wordsize.h
index 00e88b0628..01245a5b71 100644
--- a/sysdeps/s390/s390-64/bits/wordsize.h
+++ b/sysdeps/s390/s390-64/bits/wordsize.h
@@ -7,5 +7,3 @@
 # define __WORDSIZE32_SIZE_ULONG       1
 # define __WORDSIZE32_PTRDIFF_LONG     0
 #endif
-
-#define __WORDSIZE_TIME64_COMPAT32     0
diff --git a/sysdeps/sparc/sparc32/bits/wordsize.h b/sysdeps/sparc/sparc32/bits/wordsize.h
index 2f66f10d72..10b73267f0 100644
--- a/sysdeps/sparc/sparc32/bits/wordsize.h
+++ b/sysdeps/sparc/sparc32/bits/wordsize.h
@@ -2,10 +2,8 @@
 
 #if defined __arch64__ || defined __sparcv9
 # define __WORDSIZE	64
-# define __WORDSIZE_TIME64_COMPAT32	1
 #else
 # define __WORDSIZE	32
-# define __WORDSIZE_TIME64_COMPAT32	0
 # define __WORDSIZE32_SIZE_ULONG	0
 # define __WORDSIZE32_PTRDIFF_LONG	0
 #endif
diff --git a/sysdeps/sparc/sparc64/bits/wordsize.h b/sysdeps/sparc/sparc64/bits/wordsize.h
index 2f66f10d72..10b73267f0 100644
--- a/sysdeps/sparc/sparc64/bits/wordsize.h
+++ b/sysdeps/sparc/sparc64/bits/wordsize.h
@@ -2,10 +2,8 @@
 
 #if defined __arch64__ || defined __sparcv9
 # define __WORDSIZE	64
-# define __WORDSIZE_TIME64_COMPAT32	1
 #else
 # define __WORDSIZE	32
-# define __WORDSIZE_TIME64_COMPAT32	0
 # define __WORDSIZE32_SIZE_ULONG	0
 # define __WORDSIZE32_PTRDIFF_LONG	0
 #endif
diff --git a/sysdeps/unix/sysv/linux/alpha/bits/wordsize.h b/sysdeps/unix/sysv/linux/alpha/bits/wordsize.h
index 74289c244a..6d955a9f27 100644
--- a/sysdeps/unix/sysv/linux/alpha/bits/wordsize.h
+++ b/sysdeps/unix/sysv/linux/alpha/bits/wordsize.h
@@ -16,4 +16,3 @@
    <https://www.gnu.org/licenses/>.  */
 
 #define __WORDSIZE	64
-#define __WORDSIZE_TIME64_COMPAT32	0
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/wordsize.h b/sysdeps/unix/sysv/linux/powerpc/bits/wordsize.h
index 04ca9debf0..df1aa27244 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/wordsize.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/wordsize.h
@@ -2,10 +2,8 @@
 
 #if defined __powerpc64__
 # define __WORDSIZE	64
-# define __WORDSIZE_TIME64_COMPAT32	1
 #else
 # define __WORDSIZE	32
-# define __WORDSIZE_TIME64_COMPAT32	0
 # define __WORDSIZE32_SIZE_ULONG	0
 # define __WORDSIZE32_PTRDIFF_LONG	0
 #endif
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/wordsize.h b/sysdeps/unix/sysv/linux/sparc/bits/wordsize.h
index 7562875ee2..10b73267f0 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/wordsize.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/wordsize.h
@@ -2,10 +2,8 @@
 
 #if defined __arch64__ || defined __sparcv9
 # define __WORDSIZE	64
-# define __WORDSIZE_TIME64_COMPAT32	1
 #else
 # define __WORDSIZE	32
 # define __WORDSIZE32_SIZE_ULONG	0
 # define __WORDSIZE32_PTRDIFF_LONG	0
-# define __WORDSIZE_TIME64_COMPAT32	0
 #endif
diff --git a/sysdeps/wordsize-32/bits/wordsize.h b/sysdeps/wordsize-32/bits/wordsize.h
index 759906a08d..869a7ab2aa 100644
--- a/sysdeps/wordsize-32/bits/wordsize.h
+++ b/sysdeps/wordsize-32/bits/wordsize.h
@@ -16,6 +16,5 @@
    <https://www.gnu.org/licenses/>.  */
 
 #define __WORDSIZE			32
-#define __WORDSIZE_TIME64_COMPAT32	0
 #define __WORDSIZE32_SIZE_ULONG		0
 #define __WORDSIZE32_PTRDIFF_LONG	0
diff --git a/sysdeps/wordsize-64/bits/wordsize.h b/sysdeps/wordsize-64/bits/wordsize.h
index 44b9725814..8613a6cb3c 100644
--- a/sysdeps/wordsize-64/bits/wordsize.h
+++ b/sysdeps/wordsize-64/bits/wordsize.h
@@ -16,4 +16,3 @@
    <https://www.gnu.org/licenses/>.  */
 
 #define __WORDSIZE			64
-#define __WORDSIZE_TIME64_COMPAT32	0
diff --git a/sysdeps/x86/bits/wordsize.h b/sysdeps/x86/bits/wordsize.h
index 70f652bca1..cf250cc6df 100644
--- a/sysdeps/x86/bits/wordsize.h
+++ b/sysdeps/x86/bits/wordsize.h
@@ -9,9 +9,6 @@
 #endif
 
 #ifdef __x86_64__
-# define __WORDSIZE_TIME64_COMPAT32	1
 /* Both x86-64 and x32 use the 64-bit system call interface.  */
 # define __SYSCALL_WORDSIZE		64
-#else
-# define __WORDSIZE_TIME64_COMPAT32	0
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 3/7] support: Add 'touch' command
  2020-08-05 18:59 ` [PATCH v2 3/7] support: Add 'touch' command Adhemerval Zanella via Libc-alpha
@ 2020-08-05 19:08   ` DJ Delorie via Libc-alpha
  0 siblings, 0 replies; 14+ messages in thread
From: DJ Delorie via Libc-alpha @ 2020-08-05 19:08 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

Adhemerval Zanella via Libc-alpha <libc-alpha@sourceware.org> writes:
> It allow creates empty files with an specific mode.
> +	 touch MODE FILE

Ok.

> +	 - 'touch': A minimal 'touch' command to create empty files.

Ok.

> +	    else if (nt == 3 && strcmp (the_words[0], "touch") == 0)
> +	      {
> +		long int m;
> +		errno = 0;
> +		m = strtol (the_words[1], NULL, 0);
> +		TEST_COMPARE (errno, 0);
> +
> +		xopen (the_words[2], O_WRONLY | O_TRUNC | O_CREAT, m);
> +	      }

Needs an xclose() but otherwise ok.

Reviewed-by: DJ Delorie <dj@redhat.com>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/7] login: Add 64-bit time support to utmp/utmpx
  2020-08-05 18:59 ` [PATCH v2 4/7] login: Add 64-bit time support to utmp/utmpx Adhemerval Zanella via Libc-alpha
@ 2020-08-05 19:28   ` Joseph Myers
  2020-08-05 20:35     ` Adhemerval Zanella via Libc-alpha
  0 siblings, 1 reply; 14+ messages in thread
From: Joseph Myers @ 2020-08-05 19:28 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Wed, 5 Aug 2020, Adhemerval Zanella via Libc-alpha wrote:

>   - New file names are defined for _PATH_UTMP, _PATH_WTMP, and
>     _PATH_UTMP_DB (if applicable) and used as default for the new 2.33
>     utmp{x} symbols.

On architectures that already have 64-bit time in these files, I think it 
would be best to keep the same names as at present (and likewise for 
lastlog).  (I'm not particularly concerned with whether such architectures 
get (unnecessary) new symbol versions, though ideally we'd avoid code size 
increase by ensuring there is no translation logic.)  If any such 
architectures are using a different layout from the new generic one, 
despite using 64-bit times, maybe they could keep their own version of the 
layout to avoid needing multiple versions of the files?

Additions to the NEWS file are also needed to discuss these changes and 
what distributions should do on glibc upgrade.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 6/7] login: Use 64-bit time on struct lastlog
  2020-08-05 18:59 ` [PATCH v2 6/7] login: Use 64-bit time on struct lastlog Adhemerval Zanella via Libc-alpha
@ 2020-08-05 19:56   ` Florian Weimer
  2020-08-05 20:36     ` Adhemerval Zanella via Libc-alpha
  0 siblings, 1 reply; 14+ messages in thread
From: Florian Weimer @ 2020-08-05 19:56 UTC (permalink / raw)
  To: Adhemerval Zanella via Libc-alpha

* Adhemerval Zanella via Libc-alpha:

> diff --git a/bits/types/struct_lastlog.h b/bits/types/struct_lastlog.h
> index 67ffec1b08..9e8983b57d 100644
> --- a/bits/types/struct_lastlog.h
> +++ b/bits/types/struct_lastlog.h
> @@ -24,11 +24,11 @@
>     previous logins.  */
>  struct lastlog
>  {
> -#if __WORDSIZE_TIME64_COMPAT32
> -  int32_t ll_time;
> +#if __WORDSIZE == 32
> +  int64_t ll_time;
>  #else
>    __time_t ll_time;
>  #endif

Should this check for __TIMESIZE instead of __WORDSIZE?  It shouldn't
make a difference; I just think it would be clearer.

Or maybe use int64_t unconditionally?  That would be simpler.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/7] login: Add 64-bit time support to utmp/utmpx
  2020-08-05 19:28   ` Joseph Myers
@ 2020-08-05 20:35     ` Adhemerval Zanella via Libc-alpha
  2020-08-05 20:43       ` Joseph Myers
  0 siblings, 1 reply; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 20:35 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha



On 05/08/2020 16:28, Joseph Myers wrote:
> On Wed, 5 Aug 2020, Adhemerval Zanella via Libc-alpha wrote:
> 
>>   - New file names are defined for _PATH_UTMP, _PATH_WTMP, and
>>     _PATH_UTMP_DB (if applicable) and used as default for the new 2.33
>>     utmp{x} symbols.
> 
> On architectures that already have 64-bit time in these files, I think it 
> would be best to keep the same names as at present (and likewise for 
> lastlog).  (I'm not particularly concerned with whether such architectures 
> get (unnecessary) new symbol versions, though ideally we'd avoid code size 
> increase by ensuring there is no translation logic.)  If any such 
> architectures are using a different layout from the new generic one, 
> despite using 64-bit times, maybe they could keep their own version of the 
> layout to avoid needing multiple versions of the files?
> 
> Additions to the NEWS file are also needed to discuss these changes and 
> what distributions should do on glibc upgrade.
> 

I thought keeping the same filename for architectures that already
have 64-bit ut_tv member.  However, currently only s390 fits in this
category and it would make it an outlier.  It means that glibc on s390
would be the only ABI with a different _PATH_UTMP than the default one,
which I see only adds extra complexity in the transition (distro would
need to handle s390 as an exception, this will need to be properly
documented not only in glibc, it will require an arch-specific s390
path.h). 

I am not really against keep the same _PATH_UTMP and _PATH_WTMP, but
I think keeping arch-neutral tends to cause less confusion (which I 
foresee it would happen with this change anyway).

Regarding the new symbols versions, the patch already handles it 
for s390: neither on s390 nor on s390x new symbols are created.  And
utmp{x} layout is also preserved (the ABI has arch-specific 
struct_utmp.h and struct_utmpx.h). The only change is indeed new
_PATH_UTMP and _PATH_WTMP names.

I will work on a NEWS entry.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 6/7] login: Use 64-bit time on struct lastlog
  2020-08-05 19:56   ` Florian Weimer
@ 2020-08-05 20:36     ` Adhemerval Zanella via Libc-alpha
  0 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 20:36 UTC (permalink / raw)
  To: Florian Weimer, Adhemerval Zanella via Libc-alpha



On 05/08/2020 16:56, Florian Weimer wrote:
> * Adhemerval Zanella via Libc-alpha:
> 
>> diff --git a/bits/types/struct_lastlog.h b/bits/types/struct_lastlog.h
>> index 67ffec1b08..9e8983b57d 100644
>> --- a/bits/types/struct_lastlog.h
>> +++ b/bits/types/struct_lastlog.h
>> @@ -24,11 +24,11 @@
>>     previous logins.  */
>>  struct lastlog
>>  {
>> -#if __WORDSIZE_TIME64_COMPAT32
>> -  int32_t ll_time;
>> +#if __WORDSIZE == 32
>> +  int64_t ll_time;
>>  #else
>>    __time_t ll_time;
>>  #endif
> 
> Should this check for __TIMESIZE instead of __WORDSIZE?  It shouldn't
> make a difference; I just think it would be clearer.
> 
> Or maybe use int64_t unconditionally?  That would be simpler.
> 

The lastlog is not really defined in any standard, so I guess we have
this liberty here.  I agree that int64_t unconditionally is simpler.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/7] login: Add 64-bit time support to utmp/utmpx
  2020-08-05 20:35     ` Adhemerval Zanella via Libc-alpha
@ 2020-08-05 20:43       ` Joseph Myers
  2020-08-05 20:54         ` Adhemerval Zanella via Libc-alpha
  0 siblings, 1 reply; 14+ messages in thread
From: Joseph Myers @ 2020-08-05 20:43 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Wed, 5 Aug 2020, Adhemerval Zanella via Libc-alpha wrote:

> I thought keeping the same filename for architectures that already
> have 64-bit ut_tv member.  However, currently only s390 fits in this
> category and it would make it an outlier.  It means that glibc on s390

But it's not just s390.  aarch64, alpha, arc, ia64 all look like they use 
64-bit times in struct utmp.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/7] login: Add 64-bit time support to utmp/utmpx
  2020-08-05 20:43       ` Joseph Myers
@ 2020-08-05 20:54         ` Adhemerval Zanella via Libc-alpha
  0 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella via Libc-alpha @ 2020-08-05 20:54 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha



On 05/08/2020 17:43, Joseph Myers wrote:
> On Wed, 5 Aug 2020, Adhemerval Zanella via Libc-alpha wrote:
> 
>> I thought keeping the same filename for architectures that already
>> have 64-bit ut_tv member.  However, currently only s390 fits in this
>> category and it would make it an outlier.  It means that glibc on s390
> 
> But it's not just s390.  aarch64, alpha, arc, ia64 all look like they use 
> 64-bit times in struct utmp.
> 

Indeed, my mistake (I forgot not all 64-bit time_t architecture define
__WORDSIZE_TIME64_COMPAT32).  I don't have a strong opinion in fact, 
at least the change should be simple somewhat (I think adding a new
paths-utmp.h included by paths.h and defined by arch ABI that requires
it).

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2020-08-05 20:54 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-05 18:59 [PATCH v2 1/7] login: Move gnu utmpx to default implementation Adhemerval Zanella via Libc-alpha
2020-08-05 18:59 ` [PATCH v2 2/7] Consolidate and simplify internal utmp definitions Adhemerval Zanella via Libc-alpha
2020-08-05 18:59 ` [PATCH v2 3/7] support: Add 'touch' command Adhemerval Zanella via Libc-alpha
2020-08-05 19:08   ` DJ Delorie via Libc-alpha
2020-08-05 18:59 ` [PATCH v2 4/7] login: Add 64-bit time support to utmp/utmpx Adhemerval Zanella via Libc-alpha
2020-08-05 19:28   ` Joseph Myers
2020-08-05 20:35     ` Adhemerval Zanella via Libc-alpha
2020-08-05 20:43       ` Joseph Myers
2020-08-05 20:54         ` Adhemerval Zanella via Libc-alpha
2020-08-05 18:59 ` [PATCH v2 5/7] linux: Add pwrite64_nocancel Adhemerval Zanella via Libc-alpha
2020-08-05 18:59 ` [PATCH v2 6/7] login: Use 64-bit time on struct lastlog Adhemerval Zanella via Libc-alpha
2020-08-05 19:56   ` Florian Weimer
2020-08-05 20:36     ` Adhemerval Zanella via Libc-alpha
2020-08-05 18:59 ` [PATCH v2 7/7] Remove __WORDSIZE_TIME64_COMPAT32 Adhemerval Zanella via Libc-alpha

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).