Convert glibc_post_upgrade to lua.
This commit is contained in:
parent
fcb4083893
commit
34927af202
|
@ -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]);
|
|
||||||
+}
|
|
167
glibc.spec
167
glibc.spec
|
@ -87,7 +87,7 @@
|
||||||
Summary: The GNU libc libraries
|
Summary: The GNU libc libraries
|
||||||
Name: glibc
|
Name: glibc
|
||||||
Version: %{glibcversion}
|
Version: %{glibcversion}
|
||||||
Release: 22%{?dist}
|
Release: 23%{?dist}
|
||||||
|
|
||||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||||
# libraries.
|
# libraries.
|
||||||
|
@ -136,7 +136,6 @@ Source12: ChangeLog.old
|
||||||
# - See each individual patch file for origin and upstream status.
|
# - See each individual patch file for origin and upstream status.
|
||||||
# - For new patches follow template.patch format.
|
# - For new patches follow template.patch format.
|
||||||
##############################################################################
|
##############################################################################
|
||||||
Patch1: glibc-post_upgrade.patch
|
|
||||||
Patch2: glibc-fedora-nscd.patch
|
Patch2: glibc-fedora-nscd.patch
|
||||||
Patch3: glibc-rh697421.patch
|
Patch3: glibc-rh697421.patch
|
||||||
Patch4: glibc-fedora-linux-tcsetattr.patch
|
Patch4: glibc-fedora-linux-tcsetattr.patch
|
||||||
|
@ -399,8 +398,11 @@ libraries, as well as national language (locale) support.
|
||||||
/sbin/ldconfig
|
/sbin/ldconfig
|
||||||
%end
|
%end
|
||||||
|
|
||||||
# We need to run ldconfig manually because ldconfig cannot handle the
|
# We need to run ldconfig manually because __brp_ldconfig assumes that
|
||||||
# relative include path in the /etc/ld.so.conf file we gneerate.
|
# 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
|
%undefine __brp_ldconfig
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
@ -1089,10 +1091,6 @@ truncate -s 0 %{glibc_sysroot}/etc/gai.conf
|
||||||
truncate -s 0 %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache
|
truncate -s 0 %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache
|
||||||
chmod 644 %{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
|
# Install debug copies of unstripped static libraries
|
||||||
# - This step must be last in order to capture any additional static
|
# - This step must be last in order to capture any additional static
|
||||||
|
@ -1115,8 +1113,8 @@ rm -rf %{glibc_sysroot}%{_prefix}/share/zoneinfo
|
||||||
#
|
#
|
||||||
# XXX: Ideally ld.so.conf should have the timestamp of the spec file, but there
|
# 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,
|
# 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
|
# which is to at least keep the timestamp consistent. The choice of using
|
||||||
# glibc_post_upgrade.c is arbitrary.
|
# SOURCE0 is arbitrary.
|
||||||
touch -r %{SOURCE0} %{glibc_sysroot}/etc/ld.so.conf
|
touch -r %{SOURCE0} %{glibc_sysroot}/etc/ld.so.conf
|
||||||
touch -r sunrpc/etc.rpc %{glibc_sysroot}/etc/rpc
|
touch -r sunrpc/etc.rpc %{glibc_sysroot}/etc/rpc
|
||||||
|
|
||||||
|
@ -1341,8 +1339,9 @@ chmod 0444 master.filelist
|
||||||
# - The partial (lib*_p.a) static libraries, include files.
|
# - The partial (lib*_p.a) static libraries, include files.
|
||||||
# - The static files, objects, unversioned DSOs, and nscd.
|
# - The static files, objects, unversioned DSOs, and nscd.
|
||||||
# - The bin, locale, some sbin, and share.
|
# - The bin, locale, some sbin, and share.
|
||||||
# - The use of [^gi] is meant to exclude all files except glibc_post_upgrade,
|
# - We want iconvconfig in the main package and we do this by using
|
||||||
# and iconvconfig, which we want in the main packages.
|
# 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 the libnss files (we add back the ones we want later).
|
||||||
# - All bench test binaries.
|
# - All bench test binaries.
|
||||||
# - The aux-cache, since it's handled specially in the files section.
|
# - The aux-cache, since it's handled specially in the files section.
|
||||||
|
@ -1357,7 +1356,7 @@ cat master.filelist \
|
||||||
-e 'nscd' \
|
-e 'nscd' \
|
||||||
-e '%{_prefix}/bin' \
|
-e '%{_prefix}/bin' \
|
||||||
-e '%{_prefix}/lib/locale' \
|
-e '%{_prefix}/lib/locale' \
|
||||||
-e '%{_prefix}/sbin/[^gi]' \
|
-e '%{_prefix}/sbin/[^i]' \
|
||||||
-e '%{_prefix}/share' \
|
-e '%{_prefix}/share' \
|
||||||
-e '/var/db/Makefile' \
|
-e '/var/db/Makefile' \
|
||||||
-e '/libnss_.*\.so[0-9.]*$' \
|
-e '/libnss_.*\.so[0-9.]*$' \
|
||||||
|
@ -1433,10 +1432,13 @@ grep '%{_libdir}/lib.*\.a' < master.filelist \
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# All of the bin and certain sbin files go into the common package except
|
# 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
|
# iconvconfig which needs to go in glibc. Likewise nscd is excluded because
|
||||||
# nscd is excluded because it goes in nscd.
|
# it goes in nscd. The iconvconfig binary is kept in the main glibc package
|
||||||
|
# because we use it in the post-install scriptlet to rebuild the
|
||||||
|
# gconv-modules.cache.
|
||||||
grep '%{_prefix}/bin' master.filelist >> common.filelist
|
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
|
| grep -v 'nscd' >> common.filelist
|
||||||
# All of the files under share go into the common package since they should be
|
# All of the files under share go into the common package since they should be
|
||||||
# multilib-independent.
|
# multilib-independent.
|
||||||
|
@ -1736,7 +1738,135 @@ if rpm.vercmp(rel, required) < 0 then
|
||||||
error("FATAL: kernel too old", 0)
|
error("FATAL: kernel too old", 0)
|
||||||
end
|
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.
|
||||||
|
|
||||||
|
-- Full set of libraries glibc may install.
|
||||||
|
install_libs = { "anl", "BrokenLocale", "c", "dl", "m", "mvec",
|
||||||
|
"nss_compat", "nss_db", "nss_dns", "nss_files",
|
||||||
|
"nss_hesiod", "pthread", "resolv", "rt", "SegFault",
|
||||||
|
"thread_db", "util" }
|
||||||
|
|
||||||
|
-- We are going to remove these libraries. Generally speaking we remove
|
||||||
|
-- all core libraries in the multilib directory.
|
||||||
|
-- We employ a tight match where X.Y is in [2.0,9.9*], so we would
|
||||||
|
-- match "libc-2.0.so" and so on up to "libc-9.9*".
|
||||||
|
remove_regexps = {}
|
||||||
|
for i = 1, #install_libs do
|
||||||
|
remove_regexps[i] = ("lib" .. install_libs[i]
|
||||||
|
.. "%%-[2-9]%%.[0-9]+%%.so$")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Two exceptions:
|
||||||
|
remove_regexps[#install_libs + 1] = "libthread_db%%-1%%.0%%.so"
|
||||||
|
remove_regexps[#install_libs + 2] = "libSegFault%%.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
|
||||||
|
|
||||||
%pre headers
|
%pre headers
|
||||||
# this used to be a link and it is causing nightmares now
|
# this used to be a link and it is causing nightmares now
|
||||||
|
@ -1855,6 +1985,9 @@ fi
|
||||||
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sat Jun 01 2019 Carlos O'Donell <carlos@redhat.com> - 2.29.9000-23
|
||||||
|
- Convert glibc_post_upgrade to lua.
|
||||||
|
|
||||||
* Sat Jun 01 2019 Florian Weimer <fweimer@redhat.com> - 2.29.9000-22
|
* Sat Jun 01 2019 Florian Weimer <fweimer@redhat.com> - 2.29.9000-22
|
||||||
- Remove support for filtering glibc-all-langpacks (#1715891)
|
- Remove support for filtering glibc-all-langpacks (#1715891)
|
||||||
- Auto-sync with upstream branch master,
|
- Auto-sync with upstream branch master,
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue