*
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2012, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
#define MAXIMUM_WIPE_BYTES 1024 * 1024 * 32 /* 32 MiB */
-static ssize_t _crypt_wipe_zero(int fd, char *buffer, uint64_t offset, uint64_t size)
+static ssize_t _crypt_wipe_zero(int fd, int bsize, char *buffer,
+ uint64_t offset, uint64_t size)
{
memset(buffer, 0, size);
- return write_lseek_blockwise(fd, buffer, size, offset);
+ return write_lseek_blockwise(fd, bsize, buffer, size, offset);
}
-static ssize_t _crypt_wipe_random(int fd, char *buffer, uint64_t offset, uint64_t size)
+static ssize_t _crypt_wipe_random(int fd, int bsize, char *buffer,
+ uint64_t offset, uint64_t size)
{
if (crypt_random_get(NULL, buffer, size, CRYPT_RND_NORMAL) < 0)
return -EINVAL;
- return write_lseek_blockwise(fd, buffer, size, offset);
+ return write_lseek_blockwise(fd, bsize, buffer, size, offset);
}
/*
}
}
-static ssize_t _crypt_wipe_disk(int fd, char *buffer, uint64_t offset, uint64_t size)
+static ssize_t _crypt_wipe_disk(int fd, int bsize, char *buffer,
+ uint64_t offset, uint64_t size)
{
int r;
unsigned int i;
if (r < 0)
return r;
- written = write_lseek_blockwise(fd, buffer, size, offset);
+ written = write_lseek_blockwise(fd, bsize, buffer, size, offset);
if (written < 0 || written != (ssize_t)size)
return written;
}
/* Rewrite it finally with random */
- return _crypt_wipe_random(fd, buffer, offset, size);
+ return _crypt_wipe_random(fd, bsize, buffer, offset, size);
}
-static ssize_t _crypt_wipe_ssd(int fd, char *buffer, uint64_t offset, uint64_t size)
+static ssize_t _crypt_wipe_ssd(int fd, int bsize, char *buffer,
+ uint64_t offset, uint64_t size)
{
// FIXME: for now just rewrite it by random
- return _crypt_wipe_random(fd, buffer, offset, size);
+ return _crypt_wipe_random(fd, bsize, buffer, offset, size);
}
-int crypt_wipe(const char *device,
+int crypt_wipe(struct device *device,
uint64_t offset,
uint64_t size,
crypt_wipe_type type,
{
struct stat st;
char *buffer;
- int devfd, flags, rotational;
+ int devfd, flags, rotational, bsize;
ssize_t written;
if (!size || size % SECTOR_SIZE || (size > MAXIMUM_WIPE_BYTES)) {
log_dbg("Unsuported wipe size for device %s: %ld.",
- device, (unsigned long)size);
+ device_path(device), (unsigned long)size);
return -EINVAL;
}
- if (stat(device, &st) < 0) {
- log_dbg("Device %s not found.", device);
+ if (stat(device_path(device), &st) < 0) {
+ log_dbg("Device %s not found.", device_path(device));
return -EINVAL;
}
- if (type == CRYPT_WIPE_DISK) {
+ if (type == CRYPT_WIPE_DISK && S_ISBLK(st.st_mode)) {
+ rotational = 0;
if (!crypt_sysfs_get_rotational(major(st.st_rdev),
minor(st.st_rdev),
&rotational))
type = CRYPT_WIPE_SSD;
}
+ bsize = device_block_size(device);
+ if (bsize <= 0)
+ return -EINVAL;
+
buffer = malloc(size);
if (!buffer)
return -ENOMEM;
if (exclusive && S_ISBLK(st.st_mode))
flags |= O_EXCL;
- devfd = open(device, flags);
+ /* coverity[toctou] */
+ devfd = open(device_path(device), flags);
if (devfd == -1) {
free(buffer);
- return errno == EBUSY ? -EBUSY : -EINVAL;
+ return errno ? -errno : -EINVAL;
}
// FIXME: use fixed block size and loop here
switch (type) {
case CRYPT_WIPE_ZERO:
- written = _crypt_wipe_zero(devfd, buffer, offset, size);
+ written = _crypt_wipe_zero(devfd, bsize, buffer, offset, size);
break;
case CRYPT_WIPE_DISK:
- written = _crypt_wipe_disk(devfd, buffer, offset, size);
+ written = _crypt_wipe_disk(devfd, bsize, buffer, offset, size);
break;
case CRYPT_WIPE_SSD:
- written = _crypt_wipe_ssd(devfd, buffer, offset, size);
+ written = _crypt_wipe_ssd(devfd, bsize, buffer, offset, size);
break;
case CRYPT_WIPE_RANDOM:
- written = _crypt_wipe_random(devfd, buffer, offset, size);
+ written = _crypt_wipe_random(devfd, bsize, buffer, offset, size);
break;
default:
log_dbg("Unsuported wipe type requested: (%d)", type);