Signed-off-by: Will Miles <wmi...@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

Reply via email to