Version 1.11.19.
[libguestfs.git] / daemon / zero.c
index 43089e0..c8e79ae 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
@@ -62,9 +62,10 @@ do_zero (const char *device)
 int
 do_zero_device (const char *device)
 {
-  int64_t size = do_blockdev_getsize64 (device);
-  if (size == -1)
+  int64_t ssize = do_blockdev_getsize64 (device);
+  if (ssize == -1)
     return -1;
+  uint64_t size = (uint64_t) ssize;
 
   int fd = open (device, O_WRONLY);
   if (fd == -1) {
@@ -75,8 +76,16 @@ do_zero_device (const char *device)
   char buf[1024*1024];
   memset (buf, 0, sizeof buf);
 
-  while (size > 0) {
-    size_t n = (size_t) size > sizeof buf ? sizeof buf : (size_t) size;
+  uint64_t pos = 0;
+
+  while (pos < size) {
+    uint64_t n64 = size - pos;
+    size_t n;
+    if (n64 > sizeof buf)
+      n = sizeof buf;
+    else
+      n = (size_t) n64; /* safe because of if condition */
+
     ssize_t r = write (fd, buf, n);
     if (r == -1) {
       reply_with_perror ("write: %s (with %" PRId64 " bytes left to write)",
@@ -84,7 +93,9 @@ do_zero_device (const char *device)
       close (fd);
       return -1;
     }
-    size -= r;
+
+    pos += r;
+    notify_progress (pos, size);
   }
 
   if (close (fd) == -1) {
@@ -94,3 +105,76 @@ do_zero_device (const char *device)
 
   return 0;
 }
+
+static char zero[BUFSIZ];
+
+int
+do_is_zero (const char *path)
+{
+  int fd;
+  char buf[BUFSIZ];
+  ssize_t r;
+
+  CHROOT_IN;
+  fd = open (path, O_RDONLY);
+  CHROOT_OUT;
+
+  if (fd == -1) {
+    reply_with_perror ("open: %s", path);
+    return -1;
+  }
+
+  while ((r = read (fd, buf, sizeof buf)) > 0) {
+    if (memcmp (buf, zero, r) != 0) {
+      close (fd);
+      return 0;
+    }
+  }
+
+  if (r == -1) {
+    reply_with_perror ("read: %s", path);
+    close (fd);
+    return -1;
+  }
+
+  if (close (fd) == -1) {
+    reply_with_perror ("close: %s", path);
+    return -1;
+  }
+
+  return 1;
+}
+
+int
+do_is_zero_device (const char *device)
+{
+  int fd;
+  char buf[BUFSIZ];
+  ssize_t r;
+
+  fd = open (device, O_RDONLY);
+  if (fd == -1) {
+    reply_with_perror ("open: %s", device);
+    return -1;
+  }
+
+  while ((r = read (fd, buf, sizeof buf)) > 0) {
+    if (memcmp (buf, zero, r) != 0) {
+      close (fd);
+      return 0;
+    }
+  }
+
+  if (r == -1) {
+    reply_with_perror ("read: %s", device);
+    close (fd);
+    return -1;
+  }
+
+  if (close (fd) == -1) {
+    reply_with_perror ("close: %s", device);
+    return -1;
+  }
+
+  return 1;
+}