Signed-off-by: Will Miles <wmiles@sgl.com> --- lib/libalpm/diskspace.c | 37 ++++++++++++++++++++++++++ lib/libalpm/util.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ src/pacman/pacman.c | 4 +++ 3 files changed, 110 insertions(+) diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 3b496c2..4bd1821 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -119,6 +119,43 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle) } endmntent(fp); +#elif defined(__QNX__) + /* QNX + * This is done the long way via a system command + * TODO: walk /proc/mount + */ + char buffer[_POSIX_PATH_MAX]; + FILE *cmd = popen("mount | cut -d ' ' -f 3", "r"); + struct statvfs fsp; + + if(cmd == NULL) { + _alpm_log(handle, ALPM_LOG_WARNING, "Failed to get mount list: %s", strerror(errno)); + return NULL; + } + + memset(buffer, '\0', _POSIX_PATH_MAX); + + while(fgets(buffer, _POSIX_PATH_MAX-1, cmd)) { + /* eat trailing newline */ + buffer[strlen(buffer) - 1] = '\0'; + + if(statvfs(buffer, &fsp) != 0) { + _alpm_log(handle, ALPM_LOG_WARNING, + _("could not get filesystem information for %s: %s\n"), + buffer, strerror(errno)); + continue; + } + + CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + mp->mount_dir = strdup(buffer); + mp->mount_dir_len = strlen(mp->mount_dir); + memcpy(&(mp->fsp), &fsp, sizeof(struct statvfs)); + mp->read_only = fsp.f_flag & ST_RDONLY; + + mount_points = alpm_list_add(mount_points, mp); + } + + pclose(cmd); #elif defined(HAVE_GETMNTENT) && defined(HAVE_MNTTAB_H) /* Solaris, Illumos */ struct mnttab mnt; diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 4d85132..6b75cfa 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -89,6 +89,69 @@ char *strsep(char **str, const char *delims) } #endif +#ifdef __QNX__ +/** QNX execv workaround + * On QNX, we must ensure that the loader is present and the pipe server is + * started in our chroot environment. This function ensures that these + * services are correctly set up and torn down. + */ +int qnx_execv(const char *cmd, char *const argv[]) +{ + int result; + int linked_loader = 0; + int started_pipe_server = 0; + struct stat stat_tmp; + + /* Check to see if the loader exists; if not, link it */ + if(stat("/usr/lib/ldqnx.so.2", &stat_tmp) != 0) { + result = link("/lib/libc.so.3","/usr/lib/ldqnx.so.2"); + if(result != 0) { + fprintf(stderr, _("call to link loader failed (%s)\n"), strerror(errno)); + exit(1); + } + linked_loader = 1; + } + + /* Check to see if the pipe server is running; if not, start it + * Be aware that this clones the pipe fds to the pipe server, ie it is not 'fully' daemonized + * This means that the pacman host process will hang until the pipe server is terminated. + */ + if(stat("/dev/pipe", &stat_tmp) != 0) { + started_pipe_server = spawnl(P_NOWAIT,"/sbin/pipe","pipe",NULL); + if(started_pipe_server == -1) { + fprintf(stderr, _("call to start pipe server failed (%s)\n"), strerror(errno)); + if(linked_loader) { + unlink("/usr/lib/ldqnx.so.2"); + } + exit(-1); + } + } + + /* Run the program, collect the result */ + result = spawnv(P_WAIT,cmd,argv); + if(result == -1) { + result = -errno; + } else { + result = WEXITSTATUS(result); + } + + /* Clean up */ + if(started_pipe_server) { + kill(started_pipe_server, SIGTERM); + } + if(linked_loader) { + unlink("/usr/lib/ldqnx.so.2"); + } + + if(result < 0) { + fprintf(stderr, _("call to spawnv failed (%s)\n"), strerror(-result)); + exit(1); + } else { + exit(result); + } +} +#endif + int _alpm_makepath(const char *path) { return _alpm_makepath_mode(path, 0755); @@ -557,10 +620,16 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[]) exit(1); } umask(0022); + +#ifdef __QNX__ + /* never returns */ + qnx_execv(cmd, argv); +#else execv(cmd, argv); /* execv only returns if there was an error */ fprintf(stderr, _("call to execv failed (%s)\n"), strerror(errno)); exit(1); +#endif } else { /* this code runs for the parent only (wait on the child) */ int status; diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index fce0131..a419416 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -1058,7 +1058,11 @@ int main(int argc, char *argv[]) /* Set up the structure to specify the new action. */ new_action.sa_handler = handler; sigemptyset(&new_action.sa_mask); +#ifdef __QNX__ + new_action.sa_flags = 0; +#else new_action.sa_flags = SA_RESTART; +#endif /* assign our handler to any signals we care about */ for(i = 0; i < sizeof(signals) / sizeof(signals[0]); i++) { -- 2.3.0