Sophie

Sophie

distrib > Mageia > 5 > i586 > by-pkgid > 11f97bbd2adce813d2e3f0d63eb2159f > files > 76

glibc-2.20-22.mga5.src.rpm

/* 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]);
}