suppress warnings from -Wmissing-noreturn
[libguestfs.git] / src / guestfs.c
index 9560aec..0d54d65 100644 (file)
@@ -59,6 +59,7 @@
 
 #include "guestfs.h"
 #include "guestfs_protocol.h"
+#include "ignore-value.h"
 
 #ifdef HAVE_GETTEXT
 #include "gettext.h"
@@ -177,6 +178,8 @@ struct guestfs_h
 
   int memsize;                 /* Size of RAM (megabytes). */
 
+  int selinux;                  /* selinux enabled? */
+
   char *last_error;
 
   /* Callbacks. */
@@ -199,9 +202,9 @@ struct guestfs_h
 
   /* Messages sent and received from the daemon. */
   char *msg_in;
-  int msg_in_size, msg_in_allocated;
+  unsigned int msg_in_size, msg_in_allocated;
   char *msg_out;
-  int msg_out_size, msg_out_pos;
+  unsigned int msg_out_size, msg_out_pos;
 
   int msg_next_serial;
 };
@@ -537,8 +540,9 @@ guestfs_safe_memdup (guestfs_h *g, void *ptr, size_t size)
 }
 
 static int
-xwrite (int fd, const void *buf, size_t len)
+xwrite (int fd, const void *v_buf, size_t len)
 {
+  const char *buf = v_buf;
   int r;
 
   while (len > 0) {
@@ -554,8 +558,9 @@ xwrite (int fd, const void *buf, size_t len)
 }
 
 static int
-xread (int fd, void *buf, size_t len)
+xread (int fd, void *v_buf, size_t len)
 {
+  char *buf = v_buf;
   int r;
 
   while (len > 0) {
@@ -689,6 +694,19 @@ guestfs_get_memsize (guestfs_h *g)
 }
 
 int
+guestfs_set_selinux (guestfs_h *g, int selinux)
+{
+  g->selinux = selinux;
+  return 0;
+}
+
+int
+guestfs_get_selinux (guestfs_h *g)
+{
+  return g->selinux;
+}
+
+int
 guestfs_get_pid (guestfs_h *g)
 {
   if (g->pid > 0)
@@ -784,14 +802,31 @@ guestfs_add_drive (guestfs_h *g, const char *filename)
     return -1;
   }
 
-  if (access (filename, F_OK) == -1) {
-    perrorf (g, "%s", filename);
-    return -1;
+  /* cache=off improves reliability in the event of a host crash.
+   *
+   * However this option causes qemu to try to open the file with
+   * O_DIRECT.  This fails on some filesystem types (notably tmpfs).
+   * So we check if we can open the file with or without O_DIRECT,
+   * and use cache=off (or not) accordingly.
+   *
+   * This test also checks for the presence of the file, which
+   * is a documented semantic of this interface.
+   */
+  int fd = open (filename, O_RDONLY|O_DIRECT);
+  if (fd >= 0) {
+    close (fd);
+    snprintf (buf, len, "file=%s,cache=off,if=" DRIVE_IF, filename);
+  } else {
+    fd = open (filename, O_RDONLY);
+    if (fd >= 0) {
+      close (fd);
+      snprintf (buf, len, "file=%s,if=" DRIVE_IF, filename);
+    } else {
+      perrorf (g, "%s", filename);
+      return -1;
+    }
   }
 
-  /* cache=off improves reliability in the event of a host crash. */
-  snprintf (buf, len, "file=%s,cache=off,if=%s", filename, DRIVE_IF);
-
   return guestfs_config (g, "-drive", buf);
 }
 
@@ -1047,15 +1082,19 @@ guestfs_launch (guestfs_h *g)
     "udevtimeout=300 " /* good for very slow systems (RHBZ#480319) */  \
     "noapic "          /* workaround for RHBZ#502058 - ok if not SMP */ \
     "acpi=off "        /* we don't need ACPI, turn it off */           \
-    "cgroup_disable=memory " /* saves us about 5 MB of RAM */           \
-    "selinux=0 "       /* SELinux is messed up if there's no policy */
+    "cgroup_disable=memory " /* saves us about 5 MB of RAM */
 
     /* Linux kernel command line. */
     snprintf (append, sizeof append,
-              LINUX_CMDLINE "guestfs=%s:%d%s%s%s",
+              LINUX_CMDLINE
+              "guestfs=%s:%d "
+              "%s"              /* (selinux) */
+              "%s"              /* (verbose) */
+              "%s",             /* (append) */
               VMCHANNEL_ADDR, VMCHANNEL_PORT,
-              g->verbose ? " guestfs_verbose=1" : "",
-              g->append ? " " : "", g->append ? g->append : "");
+              g->selinux ? "selinux=1 enforcing=0 " : "selinux=0 ",
+              g->verbose ? "guestfs_verbose=1 " : " ",
+              g->append ? g->append : "");
 
     snprintf (memsize_str, sizeof memsize_str, "%d", g->memsize);
 
@@ -1125,11 +1164,18 @@ guestfs_launch (guestfs_h *g)
     close (1);
     close (wfd[1]);
     close (rfd[0]);
-    dup (wfd[0]);
-    dup (rfd[1]);
+
+    int fail = 0;
+    fail |= dup (wfd[0]);
+    fail |= dup (rfd[1]);
     close (wfd[0]);
     close (rfd[1]);
 
+    if (fail) {
+      perror ("dup failed");
+      _exit (1);
+    }
+
 #if 0
     /* Set up a new process group, so we can signal this process
      * and all subprocesses (eg. if qemu is really a shell script).
@@ -1582,8 +1628,10 @@ guestfs_end_busy (guestfs_h *g)
     case CONFIG:
     case READY:
       break;
+
     case LAUNCHING:
     case NO_HANDLE:
+    default:
       error (g, _("guestfs_end_busy: called when in state %d"), g->state);
       return -1;
     }
@@ -1661,7 +1709,7 @@ stdout_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data,
 
   /* In verbose mode, copy all log messages to stderr. */
   if (g->verbose)
-    write (2, buf, n);
+    ignore_value (write (STDERR_FILENO, buf, n));
 
   /* It's an actual log message, send it upwards if anyone is listening. */
   if (g->log_message_cb)
@@ -2471,7 +2519,7 @@ receive_file_data_sync (guestfs_h *g, void **buf, size_t *len_r)
 
     if (buf) {
       *buf = safe_realloc (g, *buf, len + ctx.chunks[i].data.data_len);
-      memcpy (*buf+len, ctx.chunks[i].data.data_val,
+      memcpy (((char *)*buf)+len, ctx.chunks[i].data.data_val,
               ctx.chunks[i].data.data_len);
     }
     len += ctx.chunks[i].data.data_len;
@@ -2577,6 +2625,7 @@ select_remove_handle (guestfs_main_loop *mlv, guestfs_h *g, int fd)
 }
 
 static int
+__attribute__((noreturn))
 select_add_timeout (guestfs_main_loop *mlv, guestfs_h *g, int interval,
                     guestfs_handle_timeout_cb cb, void *data)
 {
@@ -2586,6 +2635,7 @@ select_add_timeout (guestfs_main_loop *mlv, guestfs_h *g, int interval,
 }
 
 static int
+__attribute__((noreturn))
 select_remove_timeout (guestfs_main_loop *mlv, guestfs_h *g, int timer)
 {
   //struct select_main_loop *ml = (struct select_main_loop *) mlv;