From f5f8030a7f8f5a24266025eb1015dae5ab73e2dc Mon Sep 17 00:00:00 2001
From: Carlos O'Donell <carlos@redhat.com>
Date: Thu, 16 May 2019 21:43:50 -0400
Subject: [PATCH] Convert glibc_post_upgrade to lua.

---
 glibc-post_upgrade.patch | 272 --------------------------------------
 glibc.spec               | 157 +++++++++++++++++++---
 glibc_post_upgrade.c     | 274 ---------------------------------------
 3 files changed, 139 insertions(+), 564 deletions(-)
 delete mode 100644 glibc-post_upgrade.patch
 delete mode 100644 glibc_post_upgrade.c

diff --git a/glibc-post_upgrade.patch b/glibc-post_upgrade.patch
deleted file mode 100644
index a64adfc..0000000
--- a/glibc-post_upgrade.patch
+++ /dev/null
@@ -1,272 +0,0 @@
-Short description: RPM Post-upgrade cleanup program.
-Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
-Origin: PATCH
-Upstream status: not-needed
-
-A helper program is needed to clean up the system configuration
-early during RPM package installation, so that other scriptlets
-can run successfully.
-
-diff --git a/elf/Makefile b/elf/Makefile
-index 2a432d8beebcd207..368dcae477fff2ae 100644
---- a/elf/Makefile
-+++ b/elf/Makefile
-@@ -117,6 +117,14 @@ others-extras   = $(ldconfig-modules)
- endif
- endif
- 
-+# This needs to be statically linked because it is executed at a time
-+# when there might be incompatible shared objects on disk, and the
-+# purpose of this program is to remove them (among other things).
-+others-static += glibc_post_upgrade
-+others += glibc_post_upgrade
-+glibc_post_upgrade-modules := static-stubs
-+CFLAGS-glibc_post_upgrade.c += -DGCONV_MODULES_DIR='"$(gconvdir)"'
-+
- # To find xmalloc.c and xstrdup.c
- vpath %.c ../locale/programs
- 
-@@ -559,6 +567,8 @@ $(objpfx)sln: $(sln-modules:%=$(objpfx)%.o)
- 
- $(objpfx)ldconfig: $(ldconfig-modules:%=$(objpfx)%.o)
- 
-+$(objpfx)glibc_post_upgrade: $(glibc_post_upgrade-modules:%=$(objpfx)%.o)
-+
- SYSCONF-FLAGS := -D'SYSCONFDIR="$(sysconfdir)"'
- CFLAGS-ldconfig.c += $(SYSCONF-FLAGS) -D'LIBDIR="$(libdir)"' \
- 		    -D'SLIBDIR="$(slibdir)"'
-diff --git a/elf/glibc_post_upgrade.c b/elf/glibc_post_upgrade.c
-new file mode 100644
-index 0000000000000000..19b59f70e2308032
---- /dev/null
-+++ b/elf/glibc_post_upgrade.c
-@@ -0,0 +1,229 @@
-+#include <sys/types.h>
-+#include <sys/wait.h>
-+#include <stdio.h>
-+#include <errno.h>
-+#include <unistd.h>
-+#include <sys/time.h>
-+#include <dirent.h>
-+#include <stddef.h>
-+#include <fcntl.h>
-+#include <string.h>
-+
-+#define LD_SO_CONF "/etc/ld.so.conf"
-+#define ICONVCONFIG "/usr/sbin/iconvconfig"
-+
-+#define verbose_exec(failcode, path...) \
-+  do                                                    \
-+    {                                                   \
-+      char *const arr[] = { path, NULL };               \
-+      vexec (failcode, arr);                            \
-+    } while (0)
-+
-+__attribute__((noinline)) static void vexec (int failcode, char *const path[]);
-+__attribute__((noinline)) static void says (const char *str);
-+__attribute__((noinline)) static void sayn (long num);
-+__attribute__((noinline)) static void message (char *const path[]);
-+
-+int
-+main (void)
-+{
-+  char initpath[256];
-+
-+  char buffer[4096];
-+  struct pref {
-+    const char *p;
-+    int len;
-+  } prefix[] = { { "libc-", 5 }, { "libm-", 5 },
-+                 { "librt-", 6 }, { "libpthread-", 11 },
-+                 { "librtkaio-", 10 }, { "libthread_db-", 13 } };
-+  int i, j, fd;
-+  off_t base;
-+  ssize_t ret;
-+
-+  /* In order to support in-place upgrades, we must immediately remove
-+     obsolete platform directories after installing a new glibc
-+     version.  RPM only deletes files removed by updates near the end
-+     of the transaction.  If we did not remove the obsolete platform
-+     directories here, they would be preferred by the dynamic linker
-+     during the execution of subsequent RPM scriptlets, likely
-+     resulting in process startup failures.  */
-+  const char *remove_dirs[] =
-+    {
-+#if defined (__i386__)
-+      "/lib/i686",
-+      "/lib/i686/nosegneg",
-+#elif defined (__powerpc64__) && _CALL_ELF != 2
-+      "/lib64/power6",
-+#endif
-+    };
-+  for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j)
-+    {
-+      size_t rmlen = strlen (remove_dirs[j]);
-+      fd = open (remove_dirs[j], O_RDONLY);
-+      if (fd >= 0
-+          && (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
-+             >= (ssize_t) offsetof (struct dirent, d_name))
-+        {
-+          for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
-+            {
-+              struct dirent *d = (struct dirent *) (buffer + base);
-+
-+              for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
-+                if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
-+                  {
-+                    char *p = d->d_name + prefix[i].len;
-+
-+                    while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
-+                    if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
-+                        && p + 3 - d->d_name
-+                           < sizeof (initpath) - rmlen - 1)
-+                      {
-+                        memcpy (initpath, remove_dirs[j], rmlen);
-+                        initpath[rmlen] = '/';
-+                        strcpy (initpath + rmlen + 1, d->d_name);
-+                        unlink (initpath);
-+                        break;
-+                      }
-+                  }
-+              base += d->d_reclen;
-+            }
-+          close (fd);
-+        }
-+    }
-+
-+  int ldsocfd = open (LD_SO_CONF, O_RDONLY);
-+  struct stat ldsocst;
-+  if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0)
-+    {
-+      char p[ldsocst.st_size + 1];
-+      if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size)
-+        {
-+          p[ldsocst.st_size] = '\0';
-+          if (strstr (p, "include ld.so.conf.d/*.conf") == NULL)
-+            {
-+              close (ldsocfd);
-+              ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC);
-+              if (ldsocfd >= 0)
-+                {
-+                  size_t slen = strlen ("include ld.so.conf.d/*.conf\n");
-+                  if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen)
-+                      != slen
-+                      || write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size)
-+                    _exit (109);
-+                }
-+            }
-+        }
-+      if (ldsocfd >= 0)
-+        close (ldsocfd);
-+    }
-+
-+  /* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
-+     before running one of the lib's %post scriptlet.  /sbin/ldconfig will
-+     then be run by the other arch's %post.  */
-+  if (! access ("/sbin/ldconfig", X_OK))
-+    verbose_exec (110,
-+                  (char *) "/sbin/ldconfig",
-+                  (char *) "/sbin/ldconfig");
-+
-+  if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL))
-+    {
-+      const char *iconv_cache = GCONV_MODULES_DIR "/gconv-modules.cache";
-+      const char *iconv_dir = GCONV_MODULES_DIR;
-+      verbose_exec (113,
-+                    (char *) ICONVCONFIG,
-+                    (char *) "/usr/sbin/iconvconfig",
-+                    (char *) "-o",
-+                    (char *) iconv_cache,
-+                    (char *) "--nostdlib",
-+                    (char *) iconv_dir);
-+    }
-+
-+  _exit(0);
-+}
-+
-+void
-+vexec (int failcode, char *const path[])
-+{
-+  pid_t pid;
-+  int status, save_errno;
-+  int devnull = 0;
-+
-+  if (failcode < 0)
-+    {
-+      devnull = 1;
-+      failcode = -failcode;
-+    }
-+  pid = vfork ();
-+  if (pid == 0)
-+    {
-+      int fd;
-+      if (devnull && (fd = open ("/dev/null", O_WRONLY)) >= 0)
-+        {
-+          dup2 (fd, 1);
-+          dup2 (fd, 2);
-+          close (fd);
-+        }
-+      execv (path[0], path + 1);
-+      save_errno = errno;
-+      message (path);
-+      says (" exec failed with errno ");
-+      sayn (save_errno);
-+      says ("\n");
-+      _exit (failcode);
-+    }
-+  else if (pid < 0)
-+    {
-+      save_errno = errno;
-+      message (path);
-+      says (" fork failed with errno ");
-+      sayn (save_errno);
-+      says ("\n");
-+      _exit (failcode + 1);
-+    }
-+  if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
-+    {
-+      message (path);
-+      says (" child terminated abnormally\n");
-+      _exit (failcode + 2);
-+    }
-+  if (WEXITSTATUS (status))
-+    {
-+      message (path);
-+      says (" child exited with exit code ");
-+      sayn (WEXITSTATUS (status));
-+      says ("\n");
-+      _exit (WEXITSTATUS (status));
-+    }
-+}
-+
-+static void
-+says (const char *str)
-+{
-+  write (1, str, strlen (str));
-+}
-+
-+static void
-+sayn (long num)
-+{
-+  char string[sizeof (long) * 3 + 1];
-+  char *p = string + sizeof (string) - 1;
-+
-+  *p = '\0';
-+  if (num == 0)
-+    *--p = '0';
-+  else
-+    while (num)
-+      {
-+        *--p = '0' + num % 10;
-+        num = num / 10;
-+      }
-+
-+  says (p);
-+}
-+
-+static void
-+message (char *const path[])
-+{
-+  says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
-+  says (path[0]);
-+}
diff --git a/glibc.spec b/glibc.spec
index 775ecef..f87e57b 100644
--- a/glibc.spec
+++ b/glibc.spec
@@ -87,7 +87,7 @@
 Summary: The GNU libc libraries
 Name: glibc
 Version: %{glibcversion}
-Release: 21%{?dist}
+Release: 22%{?dist}
 
 # In general, GPLv2+ is used by programs, LGPLv2+ is used for
 # libraries.
@@ -137,7 +137,6 @@ Source12: ChangeLog.old
 # - See each individual patch file for origin and upstream status.
 # - For new patches follow template.patch format.
 ##############################################################################
-Patch1: glibc-post_upgrade.patch
 Patch2: glibc-fedora-nscd.patch
 Patch3: glibc-rh697421.patch
 Patch4: glibc-fedora-linux-tcsetattr.patch
@@ -401,8 +400,11 @@ libraries, as well as national language (locale) support.
 /sbin/ldconfig
 %end
 
-# We need to run ldconfig manually because ldconfig cannot handle the
-# relative include path in the /etc/ld.so.conf file we gneerate.
+# We need to run ldconfig manually because __brp_ldconfig assumes that
+# glibc itself is always installed in $RPM_BUILD_ROOT, but with sysroots
+# we may be installed into a subdirectory of that path.  Therefore we
+# unset __brp_ldconfig and run ldconfig by hand with the sysroots path
+# passed to -r.
 %undefine __brp_ldconfig
 
 ######################################################################
@@ -1094,10 +1096,6 @@ truncate -s 0 %{glibc_sysroot}/etc/gai.conf
 truncate -s 0 %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache
 chmod 644 %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache
 
-# Install the upgrade program
-install -m 700 build-%{target}/elf/glibc_post_upgrade \
-  %{glibc_sysroot}%{_prefix}/sbin/glibc_post_upgrade.%{_target_cpu}
-
 ##############################################################################
 # Install debug copies of unstripped static libraries
 # - This step must be last in order to capture any additional static
@@ -1120,8 +1118,8 @@ rm -rf %{glibc_sysroot}%{_prefix}/share/zoneinfo
 #
 # XXX: Ideally ld.so.conf should have the timestamp of the spec file, but there
 # doesn't seem to be any macro to give us that.  So we do the next best thing,
-# which is to at least keep the timestamp consistent.  The choice of using
-# glibc_post_upgrade.c is arbitrary.
+# which is to at least keep the timestamp consistent. The choice of using
+# SOURCE0 is arbitrary.
 touch -r %{SOURCE0} %{glibc_sysroot}/etc/ld.so.conf
 touch -r sunrpc/etc.rpc %{glibc_sysroot}/etc/rpc
 
@@ -1358,8 +1356,9 @@ chmod 0444 master.filelist
 # - The partial (lib*_p.a) static libraries, include files.
 # - The static files, objects, unversioned DSOs, and nscd.
 # - The bin, locale, some sbin, and share.
-#   - The use of [^gi] is meant to exclude all files except glibc_post_upgrade,
-#     and iconvconfig, which we want in the main packages.
+#   - We want iconvconfig in the main package and we do this by using
+#     a double negation of -v and [^i] so it removes all files in
+#     sbin *but* iconvconfig.
 # - All the libnss files (we add back the ones we want later).
 # - All bench test binaries.
 # - The aux-cache, since it's handled specially in the files section.
@@ -1375,7 +1374,7 @@ cat master.filelist \
 	-e 'nscd' \
 	-e '%{_prefix}/bin' \
 	-e '%{_prefix}/lib/locale' \
-	-e '%{_prefix}/sbin/[^gi]' \
+	-e '%{_prefix}/sbin/[^i]' \
 	-e '%{_prefix}/share' \
 	-e '/var/db/Makefile' \
 	-e '/libnss_.*\.so[0-9.]*$' \
@@ -1452,10 +1451,11 @@ grep '%{_libdir}/lib.*\.a' < master.filelist \
 ###############################################################################
 
 # All of the bin and certain sbin files go into the common package except
-# glibc_post_upgrade.* and iconvconfig which need to go in glibc. Likewise
-# nscd is excluded because it goes in nscd.
+# iconvconfig which needs to go in glibc. Likewise nscd is excluded because
+# it goes in nscd.
 grep '%{_prefix}/bin' master.filelist >> common.filelist
-grep '%{_prefix}/sbin/[^gi]' master.filelist \
+grep '%{_prefix}/sbin' master.filelist \
+	| grep -v '%{_prefix}/sbin/iconvconfig' \
 	| grep -v 'nscd' >> common.filelist
 # All of the files under share go into the common package since they should be
 # multilib-independent.
@@ -1758,7 +1758,126 @@ if rpm.vercmp(rel, required) < 0 then
   error("FATAL: kernel too old", 0)
 end
 
-%post -p %{_prefix}/sbin/glibc_post_upgrade.%{_target_cpu}
+%post -p <lua>
+-- We use lua's posix.exec because there may be no shell that we can
+-- run during glibc upgrade.
+function post_exec (program, ...)
+  local pid = posix.fork ()
+  if pid == 0 then
+    assert (posix.exec (program, ...))
+  elseif pid > 0 then
+    posix.wait (pid)
+  end
+end
+
+-- (1) Remove multilib libraries from previous installs.
+-- In order to support in-place upgrades, we must immediately remove
+-- obsolete platform directories after installing a new glibc
+-- version.  RPM only deletes files removed by updates near the end
+-- of the transaction.  If we did not remove the obsolete platform
+-- directories here, they may be preferred by the dynamic linker
+-- during the execution of subsequent RPM scriptlets, likely
+-- resulting in process startup failures.
+
+-- We are going to remove these libraries. Generally speaking we remove
+-- all core libraries in the multilib directory.
+-- We employ a tight match on libc-X.Y.so where X > 2 and Y > 2?, and
+-- related libraries so we would match "libc-2.20.so" and higher.
+remove_regexps = { "libc%%-[2-9][0-9]*%%.[2-9][0-9]+%%.so",
+		   "libm%%-[2-9][0-9]*%%.[2-9][0-9]+%%.so",
+		   "librt%%-[2-9][0-9]*%%.[2-9][0-9]+%%.so",
+		   "libpthread%%-[2-9][0-9]*%%.[2-9][0-9]+%%.so",
+		   "librtkaio%%-[2-9][0-9]*%%.[2-9][0-9]+%%.so",
+		   "libthread_db%%-[1-9][0-9]*%%.[0-9]+%%.so" }
+
+-- We are going to search these directories.
+local remove_dirs = { "%{_libdir}/i686",
+		      "%{_libdir}/i686/nosegneg",
+		      "%{_libdir}/power6",
+		      "%{_libdir}/power7",
+		      "%{_libdir}/power8" }
+
+-- Walk all the directories with files we need to remove...
+for _, rdir in ipairs (remove_dirs) do
+  if posix.access (rdir) then
+    -- If the directory exists we look at all the files...
+    local remove_files = posix.files (rdir)
+    for rfile in remove_files do
+      for _, rregexp in ipairs (remove_regexps) do
+	-- Does it match the regexp?
+	local dso = string.match (rfile, rregexp)
+        if (dso ~= nil) then
+	  -- Removing file...
+	  os.remove (rdir .. '/' .. rfile)
+	end
+      end
+    end
+  end
+end
+
+-- (2) Update /etc/ld.so.conf
+-- Next we update /etc/ld.so.conf to ensure that it starts with
+-- a literal "include ld.so.conf.d/*.conf".
+
+local ldsoconf = "/etc/ld.so.conf"
+local ldsoconf_tmp = "/etc/glibc_post_upgrade.ld.so.conf"
+
+if posix.access (ldsoconf) then
+
+  -- We must have a "include ld.so.conf.d/*.conf" line.
+  local have_include = false
+  for line in io.lines (ldsoconf) do
+    -- This must match, and we don't ignore whitespace.
+    if string.match (line, "^include ld.so.conf.d/%*%.conf$") ~= nil then
+      have_include = true
+    end
+  end
+
+  if not have_include then
+    -- Insert "include ld.so.conf.d/*.conf" line at the start of the
+    -- file. We only support one of these post upgrades running at
+    -- a time (temporary file name is fixed).
+    local tmp_fd = io.open (ldsoconf_tmp, "w")
+    if tmp_fd ~= nil then
+      tmp_fd:write ("include ld.so.conf.d/*.conf\n")
+      for line in io.lines (ldsoconf) do
+        tmp_fd:write (line .. "\n")
+      end
+      tmp_fd:close ()
+      local res = os.rename (ldsoconf_tmp, ldsoconf)
+      if res == nil then
+        io.stdout:write ("Error: Unable to update configuration file (rename).\n")
+      end
+    else
+      io.stdout:write ("Error: Unable to update configuration file (open).\n")
+    end
+  end
+end
+
+-- (3) Rebuild ld.so.cache early.
+-- If the format of the cache changes then we need to rebuild
+-- the cache early to avoid any problems running binaries with
+-- the new glibc.
+
+-- Note: We use _prefix because Fedora's UsrMove says so.
+post_exec ("%{_prefix}/sbin/ldconfig")
+
+-- (4) Update gconv modules cache.
+-- If the /usr/lib/gconv/gconv-modules.cache exists, then update it
+-- with the latest set of modules that were just installed.
+-- We assume that the cache is in _libdir/gconv and called
+-- "gconv-modules.cache".
+
+local iconv_dir = "%{_libdir}/gconv"
+local iconv_cache = iconv_dir .. "/gconv-modules.cache"
+if (posix.utime (iconv_cache) == 0) then
+  post_exec ("%{_prefix}/sbin/iconvconfig",
+	     "-o", iconv_cache,
+	     "--nostdlib",
+	     iconv_dir)
+else
+  io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n")
+end
 
 %posttrans all-langpacks -e -p <lua>
 -- If at the end of the transaction we are still installed
@@ -1899,6 +2018,9 @@ fi
 %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
 
 %changelog
+* Fri May 31 2019 Carlos O'Donell <carlos@redhat.com> - 2.29.9000-22
+- Convert glibc_post_upgrade to lua.
+
 * Mon May 27 2019 Arjun Shankar <arjun@redhat.com> - 2.29.9000-21
 - Auto-sync with upstream branch master,
   commit 85188d8211698d1a255f0aec6529546db5c56de3:
@@ -1930,7 +2052,6 @@ fi
 - dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once) [swbz# 24476]
 - Add missing Changelog entry
 
-
 * Wed May 15 2019 Florian Weimer <fweimer@redhat.com> - 2.29.9000-19
 - Auto-sync with upstream branch master,
   commit 32ff397533715988c19cbf3675dcbd727ec13e18:
diff --git a/glibc_post_upgrade.c b/glibc_post_upgrade.c
deleted file mode 100644
index 9014857..0000000
--- a/glibc_post_upgrade.c
+++ /dev/null
@@ -1,274 +0,0 @@
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <dirent.h>
-#include <stddef.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <elf.h>
-
-#define LD_SO_CONF "/etc/ld.so.conf"
-#define ICONVCONFIG "/usr/sbin/iconvconfig"
-
-#define verbose_exec(failcode, path...) \
-  do							\
-    {							\
-      char *const arr[] = { path, NULL };		\
-      vexec (failcode, arr);				\
-    } while (0)
-
-__attribute__((noinline)) void vexec (int failcode, char *const path[]);
-__attribute__((noinline)) void says (const char *str);
-__attribute__((noinline)) void sayn (long num);
-__attribute__((noinline)) void message (char *const path[]);
-__attribute__((noinline)) int check_elf (const char *name);
-
-int
-main (void)
-{
-  struct stat statbuf;
-  char initpath[256];
-
-  char buffer[4096];
-  struct pref {
-    char *p;
-    int len;
-  } prefix[] = { { "libc-", 5 }, { "libm-", 5 },
-		 { "librt-", 6 }, { "libpthread-", 11 },
-		 { "librtkaio-", 10 }, { "libthread_db-", 13 } };
-  int i, j, fd;
-  off_t base;
-  ssize_t ret;
-
-  /* In order to support in-place upgrades, we must immediately remove
-     obsolete platform directories after installing a new glibc
-     version.  RPM only deletes files removed by updates near the end
-     of the transaction.  If we did not remove the obsolete platform
-     directories here, they would be preferred by the dynamic linker
-     during the execution of subsequent RPM scriptlets, likely
-     resulting in process startup failures.  */
-  const char *remove_dirs[] =
-    {
-#if defined (__i386__)
-      "/lib/i686",
-      "/lib/i686/nosegneg",
-#elif defined (__powerpc64__) && _CALL_ELF != 2
-      "/lib64/power6",
-      "/lib64/power7",
-      "/lib64/power8",
-#endif
-    };
-  for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j)
-    {
-      size_t rmlen = strlen (remove_dirs[j]);
-      fd = open (remove_dirs[j], O_RDONLY);
-      if (fd >= 0
-	  && (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
-	     >= (ssize_t) offsetof (struct dirent, d_name))
-	{
-	  for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
-	    {
-	      struct dirent *d = (struct dirent *) (buffer + base);
-
-	      for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
-		if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
-		  {
-		    char *p = d->d_name + prefix[i].len;
-
-		    while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
-		    if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
-			&& p + 3 - d->d_name
-			   < sizeof (initpath) - rmlen - 1)
-		      {
-			memcpy (initpath, remove_dirs[j], rmlen);
-			initpath[rmlen] = '/';
-			strcpy (initpath + rmlen + 1, d->d_name);
-			unlink (initpath);
-			break;
-		      }
-		  }
-	      base += d->d_reclen;
-	    }
-	  close (fd);
-	}
-    }
-
-  int ldsocfd = open (LD_SO_CONF, O_RDONLY);
-  struct stat ldsocst;
-  if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0)
-    {
-      char p[ldsocst.st_size + 1];
-      if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size)
-	{
-	  p[ldsocst.st_size] = '\0';
-	  if (strstr (p, "include ld.so.conf.d/*.conf") == NULL)
-	    {
-	      close (ldsocfd);
-	      ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC);
-	      if (ldsocfd >= 0)
-		{
-		  size_t slen = strlen ("include ld.so.conf.d/*.conf\n");
-		  if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen)
-		      != slen
-		      || write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size)
-		    _exit (109);
-		}
-	    }
-	}
-      if (ldsocfd >= 0)
-	close (ldsocfd);
-    }
-
-  /* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
-     before running one of the lib's %post scriptlet.  /sbin/ldconfig will
-     then be run by the other arch's %post.  */
-  if (! access ("/sbin/ldconfig", X_OK))
-    verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig");
-
-  if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL))
-    {
-      char *iconv_cache = GCONV_MODULES_DIR"/gconv-modules.cache";
-      char *iconv_dir = GCONV_MODULES_DIR;
-      verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig",
-		    "-o", iconv_cache,
-		    "--nostdlib", iconv_dir);
-    }
-
-  _exit(0);
-}
-
-void
-vexec (int failcode, char *const path[])
-{
-  pid_t pid;
-  int status, save_errno;
-  int devnull = 0;
-
-  if (failcode < 0)
-    {
-      devnull = 1;
-      failcode = -failcode;
-    }
-  pid = vfork ();
-  if (pid == 0)
-    {
-      int fd;
-      if (devnull && (fd = open ("/dev/null", O_WRONLY)) >= 0)
-	{
-	  dup2 (fd, 1);
-	  dup2 (fd, 2);
-	  close (fd);
-	}
-      execv (path[0], path + 1);
-      save_errno = errno;
-      message (path);
-      says (" exec failed with errno ");
-      sayn (save_errno);
-      says ("\n");
-      _exit (failcode);
-    }
-  else if (pid < 0)
-    {
-      save_errno = errno;
-      message (path);
-      says (" fork failed with errno ");
-      sayn (save_errno);
-      says ("\n");
-      _exit (failcode + 1);
-    }
-  if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
-    {
-      message (path);
-      says (" child terminated abnormally\n");
-      _exit (failcode + 2);
-    }
-  if (WEXITSTATUS (status))
-    {
-      message (path);
-      says (" child exited with exit code ");
-      sayn (WEXITSTATUS (status));
-      says ("\n");
-      _exit (WEXITSTATUS (status));
-    }
-}
-
-void
-says (const char *str)
-{
-  write (1, str, strlen (str));
-}
-
-void
-sayn (long num)
-{
-  char string[sizeof (long) * 3 + 1];
-  char *p = string + sizeof (string) - 1;
-
-  *p = '\0';
-  if (num == 0)
-    *--p = '0';
-  else
-    while (num)
-      {
-	*--p = '0' + num % 10;
-	num = num / 10;
-      }
-
-  says (p);
-}
-
-void
-message (char *const path[])
-{
-  says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
-  says (path[0]);
-}
-
-int
-check_elf (const char *name)
-{
-  /* Play safe, if we can't open or read, assume it might be
-     ELF for the current arch.  */
-  int ret = 1;
-  int fd = open (name, O_RDONLY);
-  if (fd >= 0)
-    {
-      Elf32_Ehdr ehdr;
-      if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
-	  == offsetof (Elf32_Ehdr, e_version))
-	{
-	  ret = 0;
-	  if (ehdr.e_ident[EI_CLASS]
-	      == (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
-	    {
-#if defined __i386__
-	      ret = ehdr.e_machine == EM_386;
-#elif defined __x86_64__
-	      ret = ehdr.e_machine == EM_X86_64;
-#elif defined __powerpc64__
-	      ret = ehdr.e_machine == EM_PPC64;
-#elif defined __powerpc__
-	      ret = ehdr.e_machine == EM_PPC;
-#elif defined __s390__ || defined __s390x__
-	      ret = ehdr.e_machine == EM_S390;
-#elif defined __x86_64__
-	      ret = ehdr.e_machine == EM_X86_64;
-#elif defined __sparc__
-	      if (sizeof (long) == 8)
-		ret = ehdr.e_machine == EM_SPARCV9;
-	      else
-		ret = (ehdr.e_machine == EM_SPARC
-		       || ehdr.e_machine == EM_SPARC32PLUS);
-#else
-	      ret = 1;
-#endif
-	    }
-	}
-      close (fd);
-    }
-  return ret;
-}
-- 
2.21.0

