diff --git a/bits/types/struct_utmp.h b/bits/types/struct_utmp.h
index 76529ea62f..5f0d1cf822 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 8d6db50c06..d3be1ee1ed 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 5e2cb1da06..794d061604 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,16 @@ vpath %.c programs
 tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
   tst-pututxline-lockfail tst-pututxline-cache
 
+ifeq ($(have-GLIBC_2.33),yes)
+tests-container-internal := tst-utmp32
+tests-container := tst-utmp-default
+endif
+
 # 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..d28ecdca9f 100644
--- a/login/Versions
+++ b/login/Versions
@@ -45,10 +45,34 @@ libc {
     __getlogin_r_chk;
     __ptsname_r_chk;
   }
+  GLIBC_2.34 {
+    getutent;
+    getutent_r;
+    getutid;
+    getutid_r;
+    getutline;
+    getutline_r;
+    getutmp;
+    getutmpx;
+    getutxent;
+    getutxid;
+    getutxline;
+    pututline;
+    pututxline;
+    updwtmp;
+    updwtmpx;
+  }
+  GLIBC_PRIVATE {
+    # Used on compat login from libutil.
+    __utmp_convert32to64;
+  }
 }
 
 libutil {
   GLIBC_2.0 {
     forkpty; login; login_tty; logout; logwtmp; openpty;
   }
+  GLIBC_2.34 {
+    login;
+  }
 }
diff --git a/login/getutent.c b/login/getutent.c
index c2428bfb3e..57cbe76506 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 0af48acec8..72e9e0d070 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 d986b9d892..ace3e840b7 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 68f40a6e24..f763a0f748 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 2c8320c9a9..59a56d1ff8 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 39b8a5830f..0f04f9eaa0 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 60aafb5067..f2873cc9cd 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 a6794bac70..bd5a62b5fe 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 ae3b9fe7b0..ec33512eb4 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 274716bf7a..6baac67fc3 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 d280c13f1f..56cbf37dfe 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)
 }
 
 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 45419bc092..29fd77d566 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/login32.c
+++ b/login/login32.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 2008-2021 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-2021 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 8b38f1fd97..2b49dfe767 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..5cc997f97d
--- /dev/null
+++ b/login/tst-utmp-default.c
@@ -0,0 +1,292 @@
+/* Tests for UTMP functions using default and old UTMP_FILE.
+   Copyright (C) 2021 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..d4a356102a
--- /dev/null
+++ b/login/tst-utmp32.c
@@ -0,0 +1,318 @@
+/* Tests for UTMP compat mode.
+   Copyright (C) 2021 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>
+#include <support/test-driver.h>
+#include <stdio.h>
+
+/* The test check the compat utmp/utmpx routines for the 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 compat code
+      path to read/write 32-bit time_t utmp/utmpx entries.  */
+
+#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;
+
+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)
+{
+  int n;
+
+  setutent ();
+
+  n = 0;
+  while (1)
+    {
+      struct utmp32 *ut = (struct utmp32 *) getutent ();
+      if (ut == NULL)
+	break;
+      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);
+}
+
+static int
+do_test (void)
+{
+  run_test ();
+
+  utmpname (name);
+  run_test ();
+
+  return 0;
+}
+
+#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 e67a9cf2d9..e61d933aa3 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 ba06645dfd..93c3fd3f2d 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 9418afb0f4..8d55ddfa4f 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmp-convert.h
+++ b/login/utmp-convert.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 2008-2021 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-2021 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 7774a59580..43125f249d 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 351a932862..27191b23a4 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 00632ce51d..689ee82273 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;
+void __libc_setutent (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;
 
+void __libc_setutent32 (void) 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..427bd97449
--- /dev/null
+++ b/login/utmp32.c
@@ -0,0 +1,247 @@
+/* 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;
+
+  __libc_lock_lock (__libc_utmp_lock);
+
+  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_unlock (__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 002b5377d6..a3440a4c73 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 377209b26d..ee1fe51b43 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,91 @@ 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
+};
+static enum operation_mode_t cur_mode = UTMP_TIME64;
+
+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,33 +187,40 @@ file_unlock (int fd)
   __fcntl64_nocancel (fd, F_SETLKW, &fl);
 }
 
-int
-__libc_setutent (void)
+static bool
+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
 	(file_name, O_RDONLY | O_LARGEFILE | O_CLOEXEC);
       if (file_fd == -1)
-	return 0;
+	return false;
+      cur_mode = mode;
     }
 
   __lseek64 (file_fd, 0, SEEK_SET);
   file_offset = 0;
 
-  return 1;
+  return true;
 }
 
 /* Preform initialization if necessary.  */
 static bool
-maybe_setutent (void)
+maybe_setutent (enum operation_mode_t mode)
 {
-  return file_fd >= 0 || __libc_setutent ();
+  if (file_fd >= 0 && cur_mode != mode)
+    {
+      __close_nocancel_nostatus (file_fd);
+      file_fd = -1;
+      file_offset = 0;
+    }
+  return file_fd >= 0 || internal_setutent (mode);
 }
 
 /* Reads the entry at file_offset, storing it in last_entry and
@@ -177,40 +228,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 (mode)
+      || 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 +265,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;
-    }
+  if (!maybe_setutent (mode))
+    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 (mode)
+      || 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 +352,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;
+  if (!maybe_setutent (mode))
+    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 +398,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 +434,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 +462,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 +492,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 +505,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 +521,113 @@ unlock_return:
 
   return result;
 }
+
+void
+__libc_setutent (void)
+{
+  internal_setutent (UTMP_TIME64);
+}
+
+void
+__libc_setutent32 (void)
+{
+  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 c85c27fe68..c5c5bc458a 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,13 @@ __utmpname (const char *file)
 	}
     }
 
+  if (strcmp (__libc_utmp_file_name, _PATH_UTMP) == 0)
+    __libc_utmpname_mode = UTMPNAME_TIME64;
+  else if (strcmp (__libc_utmp_file_name, _PATH_UTMP_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..3bbfddf5fe
--- /dev/null
+++ b/login/utmpx32.c
@@ -0,0 +1,112 @@
+/* Compability symbols for utmpx with 32-bit entry times.
+   Copyright (C) 2008-2021 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 <stddef.h>
+#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 b9befad24e..ce1aa680a6 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..68cc4e0f46
--- /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_34
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index e10a286d2e..3a657d5e0d 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2204,6 +2204,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..a64b052368 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index bac795262d..4f91e85ba0 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2172,3 +2172,18 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libutil.abilist b/sysdeps/unix/sysv/linux/aarch64/libutil.abilist
index 99889de22e..3294de79be 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 897f70db22..764ea51779 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2254,6 +2254,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index 604d259ad6..2ebd24f3a6 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -1932,3 +1932,18 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/arc/libutil.abilist b/sysdeps/unix/sysv/linux/arc/libutil.abilist
index 61f73bc34e..6950302484 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index 094236f713..5cfcb00ddb 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -156,6 +156,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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/be/libutil.abilist b/sysdeps/unix/sysv/linux/arm/be/libutil.abilist
index cc1420e68c..d2d7724fa0 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libutil.abilist
@@ -1,3 +1,4 @@
+GLIBC_2.34 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/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index 2bb4d31e81..d140654389 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -153,6 +153,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..d2d7724fa0 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.34 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 d4291fecfb..11aa688b83 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2116,3 +2116,18 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/csky/libutil.abilist b/sysdeps/unix/sysv/linux/csky/libutil.abilist
index cbd11999a4..25006044fe 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 1fd2a862f6..14eef860ac 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2075,6 +2075,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 943331f01e..e1db1488a9 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2242,6 +2242,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index f530151bde..f5b4433142 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2107,6 +2107,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 6e76b6dcaa..213853a1f1 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -157,6 +157,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 updwtmpx F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
 GLIBC_2.4 _IO_2_1_stdin_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libutil.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libutil.abilist
index cc1420e68c..d2d7724fa0 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libutil.abilist
@@ -1,3 +1,4 @@
+GLIBC_2.34 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/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 7541b8289f..15dda47ba8 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2187,6 +2187,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index 6cf1936c42..3ffd49cbfb 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2167,3 +2167,18 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libutil.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libutil.abilist
index 0da0a40c22..eef306314b 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index 98730ebcda..2bccbe960a 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2164,3 +2164,18 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libutil.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libutil.abilist
index 0da0a40c22..eef306314b 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/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.34 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 92fa6cbc73..209f5f588b 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2158,6 +2158,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 265a49e74e..45d976790c 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2156,6 +2156,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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/libutil.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libutil.abilist
index aa2d35b323..fbff40d968 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.34 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 cfa5e1111b..ab3156c917 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2164,6 +2164,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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 8c03ac52cd..f8d0534156 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2158,6 +2158,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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 17f5609e06..f56e5ad002 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2205,3 +2205,18 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/nios2/libutil.abilist b/sysdeps/unix/sysv/linux/nios2/libutil.abilist
index 19608bd74d..7ef9a41873 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.34 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 76a16e2a6d..cfb457400c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2214,6 +2214,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 697f072fd4..e1fd74fbad 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2247,6 +2247,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index 2647bb51f1..5c9cdb33b4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2077,6 +2077,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fc74cb2c77 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.34 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 036b1c8345..4dcac4c766 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2367,3 +2367,18 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..3294de79be 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index ff3225e16f..69bc04c36c 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -1934,3 +1934,18 @@ GLIBC_2.33 write F
 GLIBC_2.33 writev F
 GLIBC_2.33 wscanf F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libutil.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libutil.abilist
index 59ae944bda..eded210f0b 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libutil.abilist
@@ -4,3 +4,4 @@ GLIBC_2.33 login_tty F
 GLIBC_2.33 logout F
 GLIBC_2.33 logwtmp F
 GLIBC_2.33 openpty F
+GLIBC_2.34 login F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index fb5ad9909f..dc4a3223e6 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2134,3 +2134,18 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 updwtmpx F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libutil.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libutil.abilist
index cbfec8d46e..ec3a638024 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.34 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 eebccece1c..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutent_r.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (C) 2008-2021 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 f50d633e48..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutid.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2008-2021 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 5039b99a94..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutid_r.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (C) 2008-2021 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 32b39575b0..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutline.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2008-2021 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 c9238c5f60..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutline_r.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2008-2021 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 6ffea2a553..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutmp.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2021 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 d91795af78..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutxent.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2021 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 d5d457d98d..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutxid.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2021 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 ab0189f653..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getutxline.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2021 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 5df028298a..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/login.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (C) 2008-2021 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 1dfabc8f37..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/pututxline.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2021 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 7ef8e85c00..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/updwtmp.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2008-2021 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 51cf1f5ae3..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/updwtmpx.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2008-2021 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 28632f72bd..dc4c926cca 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 32496e5421..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmp32.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Copyright (C) 2008-2021 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 <stdlib.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 ad7de5c455..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmpx-convert.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (C) 2008-2021 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 ed970961bf..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/utmpx32.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* Copyright (C) 2008-2021 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 <stdlib.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/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index a3a8be8910..6deb52d706 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2082,6 +2082,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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/be/libutil.abilist b/sysdeps/unix/sysv/linux/sh/be/libutil.abilist
index aa2d35b323..fbff40d968 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libutil.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/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.34 login F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index 8f505c5045..17a141d5b9 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2079,6 +2079,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 53ef6304f1..b64b351797 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2203,6 +2203,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index eba0cb156d..e3e01c29fc 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2130,6 +2130,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..fbff40d968 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.34 login F
diff --git a/sysdeps/unix/sysv/linux/utmp-path.h b/sysdeps/unix/sysv/linux/utmp-path.h
index f39222d62f..3cbcf24a41 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 17ce5dfd58..9995da84a8 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2089,6 +2089,21 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..f68fa6e9ba 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.34 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 17a1c83903..adccf45120 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2186,3 +2186,18 @@ GLIBC_2.33 mknodat F
 GLIBC_2.33 stat F
 GLIBC_2.33 stat64 F
 GLIBC_2.34 __libc_start_main F
+GLIBC_2.34 getutent F
+GLIBC_2.34 getutent_r F
+GLIBC_2.34 getutid F
+GLIBC_2.34 getutid_r F
+GLIBC_2.34 getutline F
+GLIBC_2.34 getutline_r F
+GLIBC_2.34 getutmp F
+GLIBC_2.34 getutmpx F
+GLIBC_2.34 getutxent F
+GLIBC_2.34 getutxid F
+GLIBC_2.34 getutxline F
+GLIBC_2.34 pututline F
+GLIBC_2.34 pututxline F
+GLIBC_2.34 updwtmp F
+GLIBC_2.34 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..5a66c2b333 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.34 login F
