/* skeleton based on version from Fedora Core 3 */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #include #include #include #include #include #include #include #include #include #include #include #include #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[]); int main (void) { /* First, get rid of platform-optimized libraries. We remove any we have ever built, since otherwise we might end up using some old leftover libraries when new ones aren't installed in their place anymore. */ #ifdef REMOVE_TLS_DIRS const char *library[] = {"libc.so.6", "libc.so.6.1", "libm.so.6", "libm.so.6.1", "librt.so.1", "librtkaio.so.1", "libpthread.so.0", "libthread_db.so.1"}; const char *remove_dir[] = { #ifdef __i386__ "/lib/i686/", #endif #ifdef __powerpc64__ #ifdef REMOVE_PPC_OPTIMIZE_POWER4 "/lib64/power4/", "/lib64/ppc970/", #endif #ifdef REMOVE_PPC_OPTIMIZE_POWER5 "/lib64/power5/", "/lib64/power5+/", #endif #ifdef REMOVE_PPC_OPTIMIZE_POWER6 "/lib64/power6/", "/lib64/power6x/", #endif #ifdef REMOVE_PPC_OPTIMIZE_POWER7 "/lib64/power7/", #endif #ifdef REMOVE_PPC_OPTIMIZE_CELL "/lib64/ppc-cell-be/", #endif #endif /* __powerpc64__ */ #ifdef __powerpc__ #ifdef REMOVE_PPC_OPTIMIZE_POWER4 "/lib/power4/", "/lib/ppc970/", #endif #ifdef REMOVE_PPC_OPTIMIZE_POWER5 "/lib/power5/", "/lib/power5+/", #endif #ifdef REMOVE_PPC_OPTIMIZE_POWER6 "/lib/power6/", "/lib/power6x/", #endif #ifdef REMOVE_PPC_OPTIMIZE_POWER7 "/lib/power7/", #endif #ifdef REMOVE_PPC_OPTIMIZE_CELL "/lib/ppc-cell-be/", #endif #endif /* __powerpc__ */ LIBDIR"/tls/" }; int i, j; for (i = 0; i < sizeof (remove_dir) / sizeof (remove_dir[0]); ++i) for (j = 0; j < sizeof (library) / sizeof (library[0]); j++) { char buf[strlen (remove_dir[i]) + strlen (library[j]) + 1]; char readlink_buf[(strlen (remove_dir[i]) + strlen (library[j])) * 2 + 30]; ssize_t len; char *cp; cp = stpcpy (buf, remove_dir[i]); strcpy (cp, library[j]); /* This file could be a symlink to library-%{version}.so, so check this and don't remove only the link, but also the library itself. */ cp = stpcpy (readlink_buf, remove_dir[i]); if ((len = readlink (buf, cp, (sizeof (readlink_buf) - (cp - readlink_buf) - 1))) > 0) { cp[len] = '\0'; if (cp[0] != '/') cp = readlink_buf; unlink (cp); } unlink (buf); } #endif /* 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) == 0) verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig", "-X"); if (utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL) == 0) { #ifndef ICONVCONFIG #define ICONVCONFIG "/usr/sbin/iconvconfig" #endif verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig", "-o", GCONV_MODULES_DIR"/gconv-modules.cache", "--nostdlib", GCONV_MODULES_DIR); } _exit(0); } void vexec (int failcode, char *const path[]) { pid_t pid; int status, save_errno; pid = vfork (); if (pid == 0) { 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]); }