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 -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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 16cf4c0..2dde267 100644 --- a/glibc.spec +++ b/glibc.spec @@ -87,7 +87,7 @@ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 22%{?dist} +Release: 23%{?dist} # In general, GPLv2+ is used by programs, LGPLv2+ is used for # libraries. @@ -136,7 +136,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 @@ -399,8 +398,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 ###################################################################### @@ -1089,10 +1091,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 @@ -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 # 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 @@ -1341,8 +1339,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. @@ -1357,7 +1356,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.]*$' \ @@ -1433,10 +1432,13 @@ 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. 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}/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. @@ -1736,7 +1738,135 @@ 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 +-- 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 # 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 %changelog +* Sat Jun 01 2019 Carlos O'Donell - 2.29.9000-23 +- Convert glibc_post_upgrade to lua. + * Sat Jun 01 2019 Florian Weimer - 2.29.9000-22 - Remove support for filtering glibc-all-langpacks (#1715891) - Auto-sync with upstream branch master, 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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; -}