Signed-off-by: Will Miles <wmiles@sgl.com> --- lib/libalpm/diskspace.c | 38 +++++++++++++++++++++++++++ lib/libalpm/trans.c | 37 +++++++++++++++++++++++++++ lib/libalpm/util.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ src/pacman/pacman.c | 4 +++ 4 files changed, 147 insertions(+) diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 3b496c2..5142d05 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -119,6 +119,44 @@ 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: use the /proc calls directly */ + char buffer[_POSIX_PATH_MAX]; + FILE *cmd = popen("mount | cut -d ' ' -f 3", "r"); + + 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)) { + struct statvfs fsp; + + /* 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/trans.c b/lib/libalpm/trans.c index 6a26e75..1c8196c 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -41,6 +41,43 @@ #include "alpm.h" #include "deps.h" +#ifdef __QNX__ +/* supply a workaround implementation of mkdtemp as the system does not */ +static char *mkdtemp(char *templateName) +{ + static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + const int length = strlen(templateName); + + char *XXXXXX = templateName + length - 6; + + if ((length < 6) || strncmp(XXXXXX, "XXXXXX", 6)) + return 0; + + for (int i = 0; i < 256; ++i) { + int v = rand(); + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + if (!mkdir(templateName, 0700)) + return templateName; + } + + return 0; +} +#endif + /** \addtogroup alpm_trans Transaction Functions * @brief Functions to manipulate libalpm transactions * @{ diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 4d85132..5e246df 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -89,6 +89,68 @@ 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 +619,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