blob: 57c2f264fe0b51e7397282fd8e8d2c98dc2f4719 [file] [log] [blame]
// Copyright (C) 2010 David Sugar, Tycho Softworks.
//
// This file is part of GNU uCommon C++.
//
// GNU uCommon C++ is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU uCommon C++ is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
#include <ucommon/secure.h>
using namespace UCOMMON_NAMESPACE;
static shell::flagopt helpflag('h',"--help", _TEXT("display this list"));
static shell::flagopt althelp('?', NULL, NULL);
static shell::numericopt passes('r', "--random", _TEXT("optional passes with randomized data (0-x)"), "count", 0);
static unsigned char buffer[65536];
static bool live = false;
static bool temp = false;
static void cleanup(void)
{
if(temp)
fsys::erase("zerofill.tmp");
if(live)
shell::printf("\n");
live = false;
}
static void zerofill(void)
{
fsys::offset_t pos = 0l;
ssize_t size = 65536;
unsigned long count = 0;
fsys_t fs;
temp = true;
fs.open("zerofill.tmp", 0666, fsys::STREAM);
if(!is(fs))
shell::errexit(1, "*** zerofill: %s\n",
_TEXT("cannot create temporary file"));
live = true;
while(size == 65536 && live) {
unsigned pass = 0;
while(pass < (unsigned)*passes) {
fs.seek(pos);
Random::fill(buffer, sizeof(buffer));
fs.write(buffer, sizeof(buffer));
++pass;
}
fs.seek(pos);
memset(buffer, 0, sizeof(buffer));
size = fs.write(buffer, sizeof(buffer));
pos += sizeof(buffer);
if(++count >= 256) {
shell::printf(".");
count = 0;
}
}
cleanup();
if(fs.err() != ENOSPC)
shell::errexit(3, "*** zerofill: %s\n",
_TEXT("failed before end of space"));
}
static void zerofill(const char *devname)
{
fsys::fileinfo_t ino;
fsys::offset_t pos = 0l;
ssize_t size = 65536;
unsigned long count = 0;
fsys_t fs;
if(fsys::info(devname, &ino))
shell::errexit(5, "*** zerofill: %s: %s\n",
devname, _TEXT("cannot access"));
if(!fsys::is_disk(&ino))
shell::errexit(6, "*** zerofill: %s: %s\n",
devname, _TEXT("not block device"));
fs.open(devname, fsys::WRONLY);
if(fs.err())
shell::errexit(5, "*** zerofill: %s: %s\n",
devname, _TEXT("cannot modify"));
shell::printf("%s", devname);
live = true;
while(size == 65536 && live) {
unsigned pass = 0;
while(pass < (unsigned)*passes) {
fs.seek(pos);
Random::fill(buffer, sizeof(buffer));
fs.write(buffer, sizeof(buffer));
++pass;
}
fs.seek(pos);
memset(buffer, 0, sizeof(buffer));
size = fs.write(buffer, sizeof(buffer));
pos += sizeof(buffer);
if(++count >= 256) {
shell::printf(".");
count = 0;
}
}
cleanup();
if(fs.err() != ENOSPC)
shell::errexit(3, "*** zerofill: %s\n",
_TEXT("failed before end of space"));
}
PROGRAM_MAIN(argc, argv)
{
shell::bind("zerofill");
shell args(argc, argv);
unsigned count = 0;
if(*passes < 0)
shell::errexit(2, "*** zerofill: random: %ld: %s\n",
*passes, _TEXT("negative random passes invalid"));
if(is(helpflag) || is(althelp)) {
printf("%s\n", _TEXT("Usage: zerofill [options] path..."));
printf("%s\n\n", _TEXT("Erase and fill unused space with zeros"));
printf("%s\n", _TEXT("Options:"));
shell::help();
printf("\n%s\n", _TEXT("Report bugs to dyfet@gnu.org"));
PROGRAM_EXIT(0);
}
secure::init();
shell::exiting(&cleanup);
if(!args())
zerofill();
while(count < args() && live)
zerofill(args[count++]);
PROGRAM_EXIT(0);
}