blob: 57c2f264fe0b51e7397282fd8e8d2c98dc2f4719 [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 2010 David Sugar, Tycho Softworks.
2//
3// This file is part of GNU uCommon C++.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
18#include <ucommon/secure.h>
19
20using namespace UCOMMON_NAMESPACE;
21
22static shell::flagopt helpflag('h',"--help", _TEXT("display this list"));
23static shell::flagopt althelp('?', NULL, NULL);
24static shell::numericopt passes('r', "--random", _TEXT("optional passes with randomized data (0-x)"), "count", 0);
25
26static unsigned char buffer[65536];
27static bool live = false;
28static bool temp = false;
29
30static void cleanup(void)
31{
32 if(temp)
33 fsys::erase("zerofill.tmp");
34 if(live)
35 shell::printf("\n");
36 live = false;
37}
38
39static void zerofill(void)
40{
41 fsys::offset_t pos = 0l;
42 ssize_t size = 65536;
43 unsigned long count = 0;
44 fsys_t fs;
45
46 temp = true;
47
48 fs.open("zerofill.tmp", 0666, fsys::STREAM);
49 if(!is(fs))
50 shell::errexit(1, "*** zerofill: %s\n",
51 _TEXT("cannot create temporary file"));
52
53 live = true;
54 while(size == 65536 && live) {
55 unsigned pass = 0;
56
57 while(pass < (unsigned)*passes) {
58 fs.seek(pos);
59 Random::fill(buffer, sizeof(buffer));
60 fs.write(buffer, sizeof(buffer));
61 ++pass;
62 }
63
64 fs.seek(pos);
65 memset(buffer, 0, sizeof(buffer));
66 size = fs.write(buffer, sizeof(buffer));
67 pos += sizeof(buffer);
68 if(++count >= 256) {
69 shell::printf(".");
70 count = 0;
71 }
72 }
73
74 cleanup();
75
76 if(fs.err() != ENOSPC)
77 shell::errexit(3, "*** zerofill: %s\n",
78 _TEXT("failed before end of space"));
79}
80
81static void zerofill(const char *devname)
82{
83 fsys::fileinfo_t ino;
84 fsys::offset_t pos = 0l;
85 ssize_t size = 65536;
86 unsigned long count = 0;
87 fsys_t fs;
88
89 if(fsys::info(devname, &ino))
90 shell::errexit(5, "*** zerofill: %s: %s\n",
91 devname, _TEXT("cannot access"));
92
93 if(!fsys::is_disk(&ino))
94 shell::errexit(6, "*** zerofill: %s: %s\n",
95 devname, _TEXT("not block device"));
96
97 fs.open(devname, fsys::WRONLY);
98 if(fs.err())
99 shell::errexit(5, "*** zerofill: %s: %s\n",
100 devname, _TEXT("cannot modify"));
101
102 shell::printf("%s", devname);
103
104 live = true;
105 while(size == 65536 && live) {
106 unsigned pass = 0;
107
108 while(pass < (unsigned)*passes) {
109 fs.seek(pos);
110 Random::fill(buffer, sizeof(buffer));
111 fs.write(buffer, sizeof(buffer));
112 ++pass;
113 }
114
115 fs.seek(pos);
116 memset(buffer, 0, sizeof(buffer));
117 size = fs.write(buffer, sizeof(buffer));
118 pos += sizeof(buffer);
119 if(++count >= 256) {
120 shell::printf(".");
121 count = 0;
122 }
123 }
124
125 cleanup();
126
127 if(fs.err() != ENOSPC)
128 shell::errexit(3, "*** zerofill: %s\n",
129 _TEXT("failed before end of space"));
130}
131
132PROGRAM_MAIN(argc, argv)
133{
134 shell::bind("zerofill");
135 shell args(argc, argv);
136 unsigned count = 0;
137
138 if(*passes < 0)
139 shell::errexit(2, "*** zerofill: random: %ld: %s\n",
140 *passes, _TEXT("negative random passes invalid"));
141
142 if(is(helpflag) || is(althelp)) {
143 printf("%s\n", _TEXT("Usage: zerofill [options] path..."));
144 printf("%s\n\n", _TEXT("Erase and fill unused space with zeros"));
145 printf("%s\n", _TEXT("Options:"));
146 shell::help();
147 printf("\n%s\n", _TEXT("Report bugs to dyfet@gnu.org"));
148 PROGRAM_EXIT(0);
149 }
150
151 secure::init();
152
153 shell::exiting(&cleanup);
154
155 if(!args())
156 zerofill();
157
158 while(count < args() && live)
159 zerofill(args[count++]);
160
161 PROGRAM_EXIT(0);
162}
163