diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 3c0074f..d09ba14 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -887,7 +887,8 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) } /* run ldconfig if it exists */ - _alpm_log(PM_LOG_DEBUG, "running \"ldconfig -r %s\"\n", handle->root); + _alpm_log(PM_LOG_DEBUG, "running \"ldconfig\" under chroot (%s)\n", + handle->root); _alpm_ldconfig(handle->root); return(0); diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 9dfff9c..370aa81 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -395,7 +395,8 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) /* run ldconfig if it exists */ if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) { - _alpm_log(PM_LOG_DEBUG, "running \"ldconfig -r %s\"\n", handle->root); + _alpm_log(PM_LOG_DEBUG, "running \"ldconfig\" under chroot (%s)\n", + handle->root); _alpm_ldconfig(handle->root); } diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 75f6042..06efa3b 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -456,19 +456,62 @@ int _alpm_logaction(unsigned short usesyslog, FILE *f, int _alpm_ldconfig(const char *root) { - char line[PATH_MAX]; - - snprintf(line, PATH_MAX, "%setc/ld.so.conf", root); - if(access(line, F_OK) == 0) { - snprintf(line, PATH_MAX, "%ssbin/ldconfig", root); - if(access(line, X_OK) == 0) { - char cmd[PATH_MAX]; - snprintf(cmd, PATH_MAX, "%s -r %s", line, root); - system(cmd); + pid_t pid; + char cwd[PATH_MAX]; + const char *ldconfig = "/sbin/ldconfig"; + const char *ldsoconf = "/etc/ld.so.conf"; + int retval = 0; + + /* Flush open fds before fork() to avoid cloning buffers */ + fflush(NULL); + + pid = fork(); + if(pid == -1) { + _alpm_log(PM_LOG_ERROR, _("could not fork a new process (%s)\n"), + strerror(errno)); + retval = 1; + } + if(pid == 0) { + /* this code runs for the child only (the actual chroot/exec) */ + _alpm_log(PM_LOG_DEBUG, "chrooting in %s\n", root); + if(chroot(root) != 0) { + _alpm_log(PM_LOG_ERROR, _("could not change directory to / (%s)\n"), + strerror(errno)); + exit(1); + } + if(access(ldsoconf, F_OK) == 0) { + if(access(ldconfig, X_OK) == 0) { + if (execl(ldconfig, ldconfig, (char *) NULL) == -1) { + _alpm_log(PM_LOG_DEBUG, "execl() call failed (%s)\n", + strerror(errno)); + exit(1); + } + } + } + exit(0); + } else { + /* this code runs for the parent only (wait on the child) */ + pid_t retpid; + int status; + while((retpid = waitpid(pid, &status, 0)) == -1 && errno == EINTR); + if(retpid == -1) { + _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"), + strerror(errno)); + retval = 1; + } else { + if(WIFEXITED(status)) { + _alpm_log(PM_LOG_DEBUG, "call to waitpid succeeded\n"); + if(WEXITSTATUS(status) != 0) { + retval = 1; + } + } } } + if(retval != 0) { + _alpm_log(PM_LOG_ERROR, _("ldconfig failed to execute correctly\n")); + } - return(0); + return(retval); } /* Helper function for comparing strings using the