mirror of
https://abf.rosa.ru/djam/glibc.git
synced 2025-02-23 15:02:47 +00:00
142 lines
3.1 KiB
C
142 lines
3.1 KiB
C
![]() |
/* Portions derived from Fedora Core glibc_post_upgrade.c */
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <limits.h>
|
||
|
#include <errno.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/wait.h>
|
||
|
#include <sys/types.h>
|
||
|
|
||
|
#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]);
|
||
|
}
|