/* Portions derived from Fedora Core glibc_post_upgrade.c */ #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(int argc, char *argv[]) { static const char *libs[] = { "libc.so.6", "libm.so.6", "libpthread.so.0", "librt.so.1", "libthread_db.so.1" }; static const char *dirs[] = { SLIBDIR "/tls" }; int i, j, ret; /* Remove obsolete libraries. */ for (i = 0; i < sizeof(dirs) / sizeof(dirs[0]); i++) { for (j = 0; j < sizeof(libs) / sizeof(libs[0]); j++) { char path[PATH_MAX], temp_path[PATH_MAX]; ret = snprintf(path, sizeof(path), "%s/%s", dirs[i], libs[j]); if (ret < 0 || ret >= sizeof(path)) continue; if ((ret = readlink(path, temp_path, sizeof(temp_path) - 1)) != -1) { char resolved_path[PATH_MAX]; temp_path[ret] = '\0'; if (temp_path[0] == '/') strcpy(resolved_path, temp_path); else ret = snprintf(resolved_path, sizeof(resolved_path), "%s/%s", dirs[i], temp_path); if (ret > 0 && ret < sizeof(resolved_path)) unlink(resolved_path); } unlink(path); } } /* Update ld.so.cache only. */ if (access("/sbin/ldconfig", X_OK) == 0) verbose_exec(110, "/sbin/ldconfig", "/sbin/ldconfig", "-X"); /* Delegate to ash for normal %post execution. */ argv[0] = ASH_BIN; execv(ASH_BIN, argv); return 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]); }