1 /* libguestfs - the guestfsd daemon
2 * Copyright (C) 2009-2011 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 /* Return true iff the buffer is all zero bytes.
33 * Note that gcc is smart enough to optimize this properly:
34 * http://stackoverflow.com/questions/1493936/faster-means-of-checking-for-an-empty-buffer-in-c/1493989#1493989
37 is_zero (const char *buffer, size_t size)
41 for (i = 0; i < size; ++i) {
49 static const char zero_buf[4096];
52 do_zero (const char *device)
54 char buf[sizeof zero_buf];
58 fd = open (device, O_RDWR);
60 reply_with_perror ("%s", device);
64 for (i = 0; i < 32; ++i) {
65 offset = i * sizeof zero_buf;
67 /* Check if the block is already zero before overwriting it. */
68 if (pread (fd, buf, sizeof buf, offset) != sizeof buf) {
69 reply_with_perror ("pread: %s", device);
74 if (!is_zero (buf, sizeof buf)) {
75 if (pwrite (fd, zero_buf, sizeof zero_buf, offset) != sizeof zero_buf) {
76 reply_with_perror ("pwrite: %s", device);
82 notify_progress ((uint64_t) i, 32);
85 if (close (fd) == -1) {
86 reply_with_perror ("close: %s", device);
94 do_zero_device (const char *device)
96 int64_t ssize = do_blockdev_getsize64 (device);
99 uint64_t size = (uint64_t) ssize;
101 int fd = open (device, O_RDWR);
103 reply_with_perror ("%s", device);
107 char buf[sizeof zero_buf];
112 uint64_t n64 = size - pos;
114 if (n64 > sizeof buf)
117 n = (size_t) n64; /* safe because of if condition */
119 /* Check if the block is already zero before overwriting it. */
121 r = pread (fd, buf, n, pos);
123 reply_with_perror ("pread: %s at offset %" PRIu64, device, pos);
128 if (!is_zero (buf, sizeof buf)) {
129 r = pwrite (fd, zero_buf, n, pos);
131 reply_with_perror ("pwrite: %s (with %" PRId64 " bytes left to write)",
141 notify_progress (pos, size);
144 if (close (fd) == -1) {
145 reply_with_perror ("close: %s", device);
153 do_is_zero (const char *path)
160 fd = open (path, O_RDONLY);
164 reply_with_perror ("open: %s", path);
168 while ((r = read (fd, buf, sizeof buf)) > 0) {
169 if (!is_zero (buf, r)) {
176 reply_with_perror ("read: %s", path);
181 if (close (fd) == -1) {
182 reply_with_perror ("close: %s", path);
190 do_is_zero_device (const char *device)
196 fd = open (device, O_RDONLY);
198 reply_with_perror ("open: %s", device);
202 while ((r = read (fd, buf, sizeof buf)) > 0) {
203 if (!is_zero (buf, r)) {
210 reply_with_perror ("read: %s", device);
215 if (close (fd) == -1) {
216 reply_with_perror ("close: %s", device);