Sophie

Sophie

distrib > Mageia > 7 > i586 > media > core-release-src > by-pkgid > a5f4304e391322727c92f033c50b87b9 > files > 52

glibc-2.29-13.mga7.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"
  };

  /* 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.  */
  static const char *dirs[] = {
	SLIBDIR "/i686"
  };


  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("/usr/sbin/ldconfig", X_OK) == 0)
	verbose_exec(110, "/usr/sbin/ldconfig", "/usr/sbin/ldconfig", "-X");

  /* always generate the gconv-modules.cache */
  if (access("/usr/sbin/iconvconfig", X_OK) == 0)
	verbose_exec(113, "/usr/sbin/iconvconfig", "/usr/sbin/iconvconfig",
		    "-o", GCONV_DIR"/gconv-modules.cache",
		    "--nostdlib", GCONV_DIR);

  /* bail out if inside chroot */
  char pathbuf[256];
  if (readlink ("/proc/1/exe", pathbuf, 256) <= 0 ||
      readlink ("/proc/1/root", pathbuf, 256) <= 0)
  _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-wrapper: While trying to execute ");
  says (path[0]);
}