daemon: Move useful is_zero function to header file.
[libguestfs.git] / daemon / daemon.h
index 6845e1b..b4f99a8 100644 (file)
@@ -1,5 +1,5 @@
 /* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc.
+ * Copyright (C) 2009-2011 Red Hat Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 /*-- in guestfsd.c --*/
 extern int verbose;
 
+extern int autosync_umount;
+
 extern const char *sysroot;
-extern int sysroot_len;
+extern size_t sysroot_len;
 
 extern char *sysroot_path (const char *path);
 
@@ -107,7 +109,7 @@ extern uint64_t progress_hint;
 extern uint64_t optargs_bitmask;
 
 /*-- in mount.c --*/
-extern int root_mounted;
+extern int is_root_mounted (void);
 
 /*-- in stubs.c (auto-generated) --*/
 extern void dispatch_incoming_message (XDR *);
@@ -126,6 +128,9 @@ extern struct optgroup optgroups[];
 /* Use this as a replacement for sync(2). */
 extern int sync_disks (void);
 
+/*-- in ext2.c --*/
+extern int e2prog (char *name); /* Massive hack for RHEL 5. */
+
 /*-- in lvm.c --*/
 extern int lv_canonical (const char *device, char **ret);
 
@@ -150,10 +155,6 @@ extern int receive_file (receive_cb cb, void *opaque);
 
 /* daemon functions that receive files (FileIn) can call this
  * to cancel incoming transfers (eg. if there is a local error).
- *
- * If and only if this function does NOT return -2, they MUST then
- * call reply_with_*
- * (see https://bugzilla.redhat.com/show_bug.cgi?id=576879#c5).
  */
 extern int cancel_receive (void);
 
@@ -173,14 +174,49 @@ extern void reply (xdrproc_t xdrp, char *ret);
  */
 extern void notify_progress (uint64_t position, uint64_t total);
 
+/* Pulse mode progress messages.
+ *
+ * Call pulse_mode_start to start sending progress messages.
+ *
+ * Call pulse_mode_end along the ordinary exit path (ie. before a
+ * reply message is sent).
+ *
+ * Call pulse_mode_cancel along all error paths *before* any reply is
+ * sent.  pulse_mode_cancel does not modify errno, so it is safe to
+ * call it before reply_with_perror.
+ *
+ * Pulse mode and ordinary notify_progress must not be mixed.
+ */
+extern void pulse_mode_start (void);
+extern void pulse_mode_end (void);
+extern void pulse_mode_cancel (void);
+
+/* Return true iff the buffer is all zero bytes.
+ *
+ * Note that gcc is smart enough to optimize this properly:
+ * http://stackoverflow.com/questions/1493936/faster-means-of-checking-for-an-empty-buffer-in-c/1493989#1493989
+ */
+static inline int
+is_zero (const char *buffer, size_t size)
+{
+  size_t i;
+
+  for (i = 0; i < size; ++i) {
+    if (buffer[i] != 0)
+      return 0;
+  }
+
+  return 1;
+}
+
 /* Helper for functions that need a root filesystem mounted.
  * NB. Cannot be used for FileIn functions.
  */
 #define NEED_ROOT(cancel_stmt,fail_stmt)                                \
   do {                                                                 \
-    if (!root_mounted) {                                               \
-      if ((cancel_stmt) != -2)                                          \
-        reply_with_error ("%s: you must call 'mount' first to mount the root filesystem", __func__); \
+    if (!is_root_mounted ()) {                                         \
+      cancel_stmt;                                                      \
+      reply_with_error ("%s: you must call 'mount' first to mount the root filesystem", __func__); \
       fail_stmt;                                                       \
     }                                                                  \
   }                                                                    \
@@ -192,8 +228,8 @@ extern void notify_progress (uint64_t position, uint64_t total);
 #define ABS_PATH(path,cancel_stmt,fail_stmt)                            \
   do {                                                                 \
     if ((path)[0] != '/') {                                            \
-      if ((cancel_stmt) != -2)                                          \
-        reply_with_error ("%s: path must start with a / character", __func__); \
+      cancel_stmt;                                                      \
+      reply_with_error ("%s: path must start with a / character", __func__); \
       fail_stmt;                                                       \
     }                                                                  \
   } while (0)
@@ -208,18 +244,17 @@ extern void notify_progress (uint64_t position, uint64_t total);
 #define RESOLVE_DEVICE(path,cancel_stmt,fail_stmt)                      \
   do {                                                                 \
     if (STRNEQLEN ((path), "/dev/", 5)) {                              \
-      if ((cancel_stmt) != -2)                                          \
-        reply_with_error ("%s: %s: expecting a device name", __func__, (path)); \
+      cancel_stmt;                                                      \
+      reply_with_error ("%s: %s: expecting a device name", __func__, (path)); \
       fail_stmt;                                                       \
     }                                                                  \
     if (is_root_device (path))                                          \
       reply_with_error ("%s: %s: device not found", __func__, path);    \
     if (device_name_translation ((path)) == -1) {                       \
       int err = errno;                                                  \
-      int r = cancel_stmt;                                              \
+      cancel_stmt;                                                      \
       errno = err;                                                      \
-      if (r != -2)                                                      \
-        reply_with_perror ("%s: %s", __func__, path);                   \
+      reply_with_perror ("%s: %s", __func__, path);                     \
       fail_stmt;                                                       \
     }                                                                   \
   } while (0)
@@ -253,17 +288,21 @@ extern void notify_progress (uint64_t position, uint64_t total);
  */
 #define CHROOT_IN                              \
   do {                                         \
-    int __old_errno = errno;                   \
-    if (chroot (sysroot) == -1)                        \
-      perror ("CHROOT_IN: sysroot");           \
-    errno = __old_errno;                       \
+    if (sysroot_len > 0) {                      \
+      int __old_errno = errno;                 \
+      if (chroot (sysroot) == -1)               \
+        perror ("CHROOT_IN: sysroot");         \
+      errno = __old_errno;                     \
+    }                                           \
   } while (0)
 #define CHROOT_OUT                             \
   do {                                         \
-    int __old_errno = errno;                   \
-    if (chroot (".") == -1)                    \
-      perror ("CHROOT_OUT: .");                        \
-    errno = __old_errno;                       \
+    if (sysroot_len > 0) {                      \
+      int __old_errno = errno;                 \
+      if (chroot (".") == -1)                  \
+        perror ("CHROOT_OUT: .");               \
+      errno = __old_errno;                     \
+    }                                           \
   } while (0)
 
 /* Marks functions which are not implemented.