mirror of
https://github.com/martijnvanbrummelen/nwipe.git
synced 2026-02-21 22:42:29 +00:00
Compare commits
215 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf3ae6a0f6 | ||
|
|
a88eeb9383 | ||
|
|
a84894f317 | ||
|
|
5c3eed8813 | ||
|
|
4b1c7007ff | ||
|
|
970d74f0d5 | ||
|
|
c815235f7b | ||
|
|
dcfa13a8db | ||
|
|
a1560de8b5 | ||
|
|
18386f225e | ||
|
|
1f3b36f141 | ||
|
|
962e1053dd | ||
|
|
93ea5f85d0 | ||
|
|
76a7be696c | ||
|
|
630d107558 | ||
|
|
5adc34b9e3 | ||
|
|
5bc61f2bdd | ||
|
|
b55b020a83 | ||
|
|
b34c99b81b | ||
|
|
63d20dc4be | ||
|
|
2111206fa3 | ||
|
|
5263a23cd6 | ||
|
|
a6b60bfd15 | ||
|
|
d8d627dce3 | ||
|
|
95d0b3f382 | ||
|
|
055d2e8b0c | ||
|
|
9f0674b3b9 | ||
|
|
5f332a407d | ||
|
|
543a880064 | ||
|
|
62c604bc0e | ||
|
|
2bc62a7217 | ||
|
|
7f5bc5aa34 | ||
|
|
7fa5c98023 | ||
|
|
4e159a902c | ||
|
|
3090b0682f | ||
|
|
d2dff52407 | ||
|
|
58a5184c88 | ||
|
|
6dcaaa6920 | ||
|
|
8e9e2ae90f | ||
|
|
02e356e0ec | ||
|
|
12063ad954 | ||
|
|
66d239c980 | ||
|
|
462777d92b | ||
|
|
69c9d7d6c5 | ||
|
|
fffee8bb34 | ||
|
|
b8a536a02f | ||
|
|
0c542660ff | ||
|
|
412917ab17 | ||
|
|
f5501ccc45 | ||
|
|
d819330583 | ||
|
|
2061346ace | ||
|
|
69fed30dde | ||
|
|
7cc1a68a89 | ||
|
|
ab6c4c0014 | ||
|
|
22f596c228 | ||
|
|
be0de995f8 | ||
|
|
24a3eb5734 | ||
|
|
5f14819e65 | ||
|
|
e06db0702b | ||
|
|
1e02b754ff | ||
|
|
4a1690be59 | ||
|
|
b826ce9fc5 | ||
|
|
9ebed56d43 | ||
|
|
c03ec324ba | ||
|
|
fb27ab8d55 | ||
|
|
c7d486f776 | ||
|
|
69b125ba4d | ||
|
|
3e15e6ef3c | ||
|
|
2e7de74202 | ||
|
|
21b5190fc4 | ||
|
|
d61b9005c3 | ||
|
|
13ecd9d268 | ||
|
|
e24d7992ef | ||
|
|
948813a692 | ||
|
|
4abff9e287 | ||
|
|
2102301382 | ||
|
|
9b2f71d4e7 | ||
|
|
c54a1296aa | ||
|
|
e543f54029 | ||
|
|
d4261b8e37 | ||
|
|
a7982c8579 | ||
|
|
9f6e2de116 | ||
|
|
337223a126 | ||
|
|
496e51d84e | ||
|
|
ca6b829687 | ||
|
|
2f1e87f09b | ||
|
|
eb1297913a | ||
|
|
7c10bc85a3 | ||
|
|
d830db3c1c | ||
|
|
4075b4b50e | ||
|
|
69d6d9708c | ||
|
|
cbe1d83801 | ||
|
|
0df4678fbc | ||
|
|
18e542bad7 | ||
|
|
24d294cf6f | ||
|
|
08c2b54a3f | ||
|
|
8d8e2e3191 | ||
|
|
86f01f0b36 | ||
|
|
0e92a9ddee | ||
|
|
33690b9e37 | ||
|
|
b29ca4c29e | ||
|
|
cf3c6f148b | ||
|
|
65d6ab45b6 | ||
|
|
d76868617a | ||
|
|
bd59f5ac98 | ||
|
|
af30da3cc2 | ||
|
|
4cc8a34bbc | ||
|
|
b3def7c336 | ||
|
|
dc012e46b2 | ||
|
|
88e2adf6a2 | ||
|
|
ddb0ca8c35 | ||
|
|
b185818732 | ||
|
|
1335455d7e | ||
|
|
cf75391b93 | ||
|
|
082a4e53d6 | ||
|
|
a4d5164602 | ||
|
|
7d93a44f18 | ||
|
|
52df4390f7 | ||
|
|
92a6a76c51 | ||
|
|
68ef665b2d | ||
|
|
fcd35ea910 | ||
|
|
5aded13bf7 | ||
|
|
5cd00da2a6 | ||
|
|
3ee514c395 | ||
|
|
fe93c77e22 | ||
|
|
d3ac79bb0e | ||
|
|
2322c690a4 | ||
|
|
243d8a5e81 | ||
|
|
4596c5f06d | ||
|
|
e91721d06b | ||
|
|
2a6d6e10df | ||
|
|
73b6b2ef6d | ||
|
|
0488138c43 | ||
|
|
57eeab2292 | ||
|
|
c3756e0f53 | ||
|
|
d140feb94b | ||
|
|
62beaca8ac | ||
|
|
497fcb73b5 | ||
|
|
00085b403e | ||
|
|
fea6facadc | ||
|
|
186bd9e03b | ||
|
|
f5db72a983 | ||
|
|
030338f1bd | ||
|
|
eee523d3d1 | ||
|
|
c3642e8904 | ||
|
|
16a3b3c487 | ||
|
|
fa9eb6892b | ||
|
|
3ed8dfd708 | ||
|
|
cbe959455a | ||
|
|
8e52c926ab | ||
|
|
22b08d43c8 | ||
|
|
98775a4837 | ||
|
|
4fe7f4a697 | ||
|
|
ddfa194ed9 | ||
|
|
b9a9386d2f | ||
|
|
8430befdc3 | ||
|
|
dc692735ce | ||
|
|
4e4c37dd4a | ||
|
|
ac0fe876a1 | ||
|
|
e46e80277d | ||
|
|
ac9757dfe7 | ||
|
|
7af0dd57c7 | ||
|
|
14d5178013 | ||
|
|
2446db741f | ||
|
|
081051c25f | ||
|
|
055b90d4c7 | ||
|
|
9789c4748f | ||
|
|
a2f70661b8 | ||
|
|
bb0019fe40 | ||
|
|
186ec9172c | ||
|
|
415f43c975 | ||
|
|
5809d0febd | ||
|
|
fdf3140249 | ||
|
|
2f7979476b | ||
|
|
c53a93ec9c | ||
|
|
6943e35a33 | ||
|
|
541a002a99 | ||
|
|
c29185999e | ||
|
|
fc406d2346 | ||
|
|
0c4493e11c | ||
|
|
acf296d25d | ||
|
|
2738522bb8 | ||
|
|
34d86e9c19 | ||
|
|
8f10179120 | ||
|
|
2b225f5cb9 | ||
|
|
8d31f2cf4a | ||
|
|
d59e0323de | ||
|
|
7ac7c80731 | ||
|
|
a1e6e3bd52 | ||
|
|
62a8e76205 | ||
|
|
fbfcbf8d34 | ||
|
|
6c99166b75 | ||
|
|
a022fffacb | ||
|
|
ec9a322683 | ||
|
|
e6dd32a74b | ||
|
|
523351531c | ||
|
|
1d83fd6f8f | ||
|
|
74243d392d | ||
|
|
06fe803eb1 | ||
|
|
298ee05b8c | ||
|
|
4928eb094e | ||
|
|
9caceaa75d | ||
|
|
75fce57ab4 | ||
|
|
e955725fc5 | ||
|
|
1c1b25e1ae | ||
|
|
d4963092dd | ||
|
|
1083207d49 | ||
|
|
458a3d780f | ||
|
|
08c9cbe9f1 | ||
|
|
e9caad3bef | ||
|
|
50e7cfaa7b | ||
|
|
ea39f57afb | ||
|
|
880823cc9b | ||
|
|
7d3a3c5f1e | ||
|
|
e33c1bb06d |
21
.github/workflows/ci_formatting.yml
vendored
Normal file
21
.github/workflows/ci_formatting.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: ci_formatting
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: updating available system dependencies
|
||||
run: sudo apt-get update
|
||||
- name: installing system dependencies
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode clang-format-7
|
||||
- name: creating autoconf files
|
||||
run: ./autogen.sh
|
||||
- name: configuring
|
||||
run: ./configure CFLAGS='-O0 -g -Wall -Wextra'
|
||||
- name: verifying code style
|
||||
run: make check-format
|
||||
7
.github/workflows/ci_ubuntu_16.04.yml
vendored
7
.github/workflows/ci_ubuntu_16.04.yml
vendored
@@ -12,13 +12,10 @@ jobs:
|
||||
- name: updating available system dependencies
|
||||
run: sudo apt-get update
|
||||
- name: installing system dependencies
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode clang-format-5.0
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode
|
||||
- name: creating autoconf files
|
||||
run: ./init.sh
|
||||
run: ./autogen.sh
|
||||
- name: configuring
|
||||
run: ./configure CFLAGS='-O0 -g -Wall -Wextra'
|
||||
- name: compiling
|
||||
run: make
|
||||
# Changing the path should no longer be necessary when clang-format6 is installed.
|
||||
- name: verifying code style
|
||||
run: export PATH=$PATH:/usr/lib/llvm-5.0/bin && make check-format
|
||||
|
||||
7
.github/workflows/ci_ubuntu_latest.yml
vendored
7
.github/workflows/ci_ubuntu_latest.yml
vendored
@@ -12,13 +12,10 @@ jobs:
|
||||
- name: updating available system dependencies
|
||||
run: sudo apt-get update
|
||||
- name: installing system dependencies
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode clang-format-5.0
|
||||
run: sudo apt-get install -y build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode
|
||||
- name: creating autoconf files
|
||||
run: ./init.sh
|
||||
run: ./autogen.sh
|
||||
- name: configuring
|
||||
run: ./configure CFLAGS='-O0 -g -Wall -Wextra'
|
||||
- name: compiling
|
||||
run: make
|
||||
# Changing the path should no longer be necessary when clang-format6 is installed.
|
||||
- name: verifying code style
|
||||
run: export PATH=$PATH:/usr/lib/llvm-5.0/bin && make check-format
|
||||
|
||||
84
CHANGELOG.md
84
CHANGELOG.md
@@ -1,25 +1,71 @@
|
||||
RELEASE NOTES
|
||||
=============
|
||||
|
||||
v0.31
|
||||
-----------------------
|
||||
- Blanking disabled in GUI for OPS2 (mandatory requirement of standard). [#326](https://github.com/martijnvanbrummelen/nwipe/pull/326)
|
||||
- Total bytes written/read for ALL passes or verifications are now logged. [#326](https://github.com/martijnvanbrummelen/nwipe/pull/326)
|
||||
- Final blanking being enabled is no longer required for verification passes. GUI Fix. [#326](https://github.com/martijnvanbrummelen/nwipe/pull/326)
|
||||
- Add a summary table to the log that shows totals for pass & verification errors. [#325](https://github.com/martijnvanbrummelen/nwipe/pull/325)
|
||||
- Fix the missing 'Verifying' message on final blanking. [#324](https://github.com/martijnvanbrummelen/nwipe/pull/324)
|
||||
- Fix prng selection always using mersenne irrespective of whatever prng the user selected. [#323](https://github.com/martijnvanbrummelen/nwipe/pull/323)
|
||||
- Fix a non functional Isaac prng. (May have never worked even in DBAN/dwipe 2.3.0). [#322](https://github.com/martijnvanbrummelen/nwipe/pull/322)
|
||||
- Log whether the prng produces a stream, if not log failure message. [#321](https://github.com/martijnvanbrummelen/nwipe/pull/321)
|
||||
- Log the specific prng that is initialised. [#320](https://github.com/martijnvanbrummelen/nwipe/pull/320)
|
||||
- Log selection details to the log. [#319](https://github.com/martijnvanbrummelen/nwipe/pull/319)
|
||||
- Improve log messaging. [#317](https://github.com/martijnvanbrummelen/nwipe/pull/317)
|
||||
- Fix auto shutdown option for some distros. [#315](https://github.com/martijnvanbrummelen/nwipe/pull/315)
|
||||
- Fix build for musl. [#301](https://github.com/martijnvanbrummelen/nwipe/pull/301)
|
||||
- Fixes to summary table & fix final status message. [311](https://github.com/martijnvanbrummelen/nwipe/pull/311/commits/12063ad9549860cd625cb91d047bd304217a9ebf)
|
||||
- Updates to --help options [#309](https://github.com/martijnvanbrummelen/nwipe/pull/309/commits/69c9d7d6c5a091c58b3e747078d0022ccdd95a99)
|
||||
- Updates to manpage. [#300](https://github.com/martijnvanbrummelen/nwipe/commit/7cc1a68a89236c4b501dde9149be82c208defccd)
|
||||
|
||||
v0.30
|
||||
-----------------------
|
||||
- Add auto power off option on completion of wipe ( --autopoweroff ) (Thanks PartialVolume)
|
||||
- Fixed --nowait option that wasn't working. (Thanks PartialVolume)
|
||||
- Add verbose option. -v, --verbose.
|
||||
- Add a spinner to the GUI for each drive being wiped. When nwipe is syncing the percentage completion pauses, having a spinner gives a clear indication that the wipe is still running. Each devices spinner disappears on completion of a given devices wipe. (Thanks PartialVolume)
|
||||
- Make log messages, especially the ones with the tag 'notice' succinct and less than 80 characters including the timestamp. This is of more importance when nwipe is used on a 80x30 terminal (ALT-F2, Shredos etc) but generally makes the logs more readable. While doing this all information was still retained. (Thanks PartialVolume)
|
||||
- Add a summary table to the log that shows each drives status, i.e. erased or failed, throughput, duration of wipe, model, serial no etc. In particular it benefits those that wipe many drives simultaneously in rack servers. At a glance any failed drives can be seen without having to browse back through the log. (Thanks PartialVolume)
|
||||
- Add ETA to --nogui wipes status when SIGUSR1 (kill -s USR1 (nwipes PID) is issued on the command line.
|
||||
- Fixed misleading throughput calculation. Throughput now shows average throughput calculated from start of wipe.
|
||||
- Fixed system info not being displayed in Debian Sid. [#229](https://github.com/martijnvanbrummelen/nwipe/issues/229) (Thanks PartialVolume)
|
||||
- Add serial number display for USB to IDE/SATA adapters. This only works if the USB to IDE/SATA adapter supports ATA pass through. See [#149](https://github.com/martijnvanbrummelen/nwipe/issues/149) for further details (Thanks PartialVolume)
|
||||
- Fixed disk capacity nomenclature, width and padding on drive selection screen. See [#237](https://github.com/martijnvanbrummelen/nwipe/issues/237) (Thanks PartialVolume)
|
||||
- Add bus type, ATA or USB, amongst others to drive selection and wipe windows. (Thanks PartialVolume)
|
||||
- Add --nousb option. If you use the option --nousb, all USB devices will be ignored. They won't show up in the GUI and they won't be wiped if you use the --nogui --autonuke command. They will even be ignored if you specifically name them on the command line.
|
||||
- Miscellaneous GUI fixes, throughput display format, percentage display format to improve column alignment when wiping multiple discs. (Thanks PartialVolume)
|
||||
- Improve visibility of failure messages with red text on white background. (Thanks PartialVolume)
|
||||
- Add NVME and VIRT (loop etc) devices to device type table for display in GUI and logs. NVME devices now show up as NVME devices rather than UNK (Thanks PartialVolume)
|
||||
- Fixed very obscure segmentation fault going back to at least 0.24 in drive selection window when resizing terminal vertical axis while drive focus symbol '>' is pointing to the last drive of a multi drive selection window. See [#248](https://github.com/martijnvanbrummelen/nwipe/pull/248) for further details (Thanks PartialVolume)
|
||||
- Warn the user if they are incorrectly typing a lower case s to start a wipe, when they should be typing a capital S [#262](https://github.com/martijnvanbrummelen/nwipe/issues/262) (Thanks PartialVolume)
|
||||
- Warn the user if they are typing capital S in order to start a wipe but haven't yet selected any drives for wiping [#261](https://github.com/martijnvanbrummelen/nwipe/issues/261) (Thanks PartialVolume)
|
||||
- Add ctrl A that toggles drive selection, all drives selected for wipe or all drives deselected. [#266](https://github.com/martijnvanbrummelen/nwipe/issues/266)
|
||||
- Fixed compilation issue with NixOS with broken musl libc error due to missing header [#275](https://github.com/martijnvanbrummelen/nwipe/issues/275)
|
||||
- Fixed status bar message showing incorrect information [#287](https://github.com/martijnvanbrummelen/nwipe/issues/287)
|
||||
- Right Justify log labels to maintain column alignment [#280](https://github.com/martijnvanbrummelen/nwipe/issues/280)
|
||||
- Added nwipe version & OS info to log [#297](https://github.com/martijnvanbrummelen/nwipe/pull/297)
|
||||
|
||||
v0.28
|
||||
-----------------------
|
||||
- Fix premature exit when terminal resized on completion of wipes (Thanks PartialVolume)
|
||||
- Fix GUI when terminal is resized, currently not handled correctly causing missing or incorrectly sized ncurses windows/panels (Thanks PartialVolume)
|
||||
- Fix GUI screen flicker under various situations. [#200](https://github.com/martijnvanbrummelen/nwipe/pull/200) Fixes [#115](https://github.com/martijnvanbrummelen/nwipe/issues/115) (Thanks PartialVolume)
|
||||
- Fix responsivness of screen during wipe when resized. Info is updated every 10th/sec. Key presses are more responsive. (Thanks PartialVolume)
|
||||
- Fix compiler warning regarding buffer overflow. Fixes [#202](https://github.com/martijnvanbrummelen/nwipe/issues/202) (Thanks PartialVolume)
|
||||
- Fix Man page (Thanks martijnvanbrummelen)
|
||||
- Fix individual device throughput. On completion of a wipe instead of the throughput calculation stopping for a completed wipe, it would continue to calculate resulting in a particular drives throughtput slowly dropping until eventually it reached zero. The overall throughput was not affected. (Thanks PartialVolume)
|
||||
- Fixed premature exit when terminal resized on completion of wipes (Thanks PartialVolume)
|
||||
- Fixed GUI when terminal is resized, currently not handled correctly causing missing or incorrectly sized ncurses windows/panels (Thanks PartialVolume)
|
||||
- Fixed GUI screen flicker under various situations. [#200](https://github.com/martijnvanbrummelen/nwipe/pull/200) Fixes [#115](https://github.com/martijnvanbrummelen/nwipe/issues/115) (Thanks PartialVolume)
|
||||
- Fixed responsivness of screen during wipe when resized. Info is updated every 10th/sec. Key presses are more responsive. (Thanks PartialVolume)
|
||||
- Fixed compiler warning regarding buffer overflow. Fixes [#202](https://github.com/martijnvanbrummelen/nwipe/issues/202) (Thanks PartialVolume)
|
||||
- Fixed Man page (Thanks martijnvanbrummelen)
|
||||
- Fixed individual device throughput. On completion of a wipe instead of the throughput calculation stopping for a completed wipe, it would continue to calculate resulting in a particular drives throughtput slowly dropping until eventually it reached zero. The overall throughput was not affected. (Thanks PartialVolume)
|
||||
|
||||
v0.27
|
||||
-----------------------
|
||||
- Add `verify` method to verify a disk is zero filled [#128](https://github.com/martijnvanbrummelen/nwipe/pull/128) (Thanks Legogizmo)
|
||||
- Add new HMG IS5 enhanced wipe method [#168](https://github.com/martijnvanbrummelen/nwipe/pull/168) (Thanks infrastation)
|
||||
- Fix percentage progress and show on completion of wipe (Thanks PartialVolume)
|
||||
- Fixed percentage progress and show on completion of wipe (Thanks PartialVolume)
|
||||
- Implement clang-format support (Thanks louib)
|
||||
- Implement more frequent disk sync support (Thanks Legogizmo)
|
||||
- Format command line help to 80 character line length [#114](https://github.com/martijnvanbrummelen/nwipe/pull/114) (Thanks PartialVolume)
|
||||
- Fix nwipe message log and missing messages that was causing segfaults under certain conditions (Thanks PartialVolume)
|
||||
- Fixed nwipe message log and missing messages that was causing segfaults under certain conditions (Thanks PartialVolume)
|
||||
- Add the Github build CI service and update Readme with build status labels (Thanks louib)
|
||||
- Miscellaneous smaller fixes
|
||||
|
||||
@@ -32,12 +78,12 @@ v0.26
|
||||
v0.25
|
||||
-----
|
||||
- Correct J=Up K=Down in footer (Thanks PartialVolume)
|
||||
- Fix segfault initialize `nwipe_gui_thread` (Thanks PartialVolume)
|
||||
- Fix memory leaks (Thanks PartialVolume)
|
||||
- Fixed segfault initialize `nwipe_gui_thread` (Thanks PartialVolume)
|
||||
- Fixed memory leaks (Thanks PartialVolume)
|
||||
- Check right pointer (Thanks PartialVolume)
|
||||
- Fix casting problem (Thanks PartialVolume)
|
||||
- Fix serial number
|
||||
- Fixes uninitialized variable warning (Thanks PartialVolume)
|
||||
- Fixed casting problem (Thanks PartialVolume)
|
||||
- Fixed serial number
|
||||
- Fixed uninitialized variable warning (Thanks PartialVolume)
|
||||
|
||||
v0.24
|
||||
-----
|
||||
@@ -56,15 +102,15 @@ v0.22
|
||||
|
||||
v0.21
|
||||
-----
|
||||
- Fix ETA not updating properly and bad total throughput display. (Thanks Niels Bassler).
|
||||
- Fixed ETA not updating properly and bad total throughput display. (Thanks Niels Bassler).
|
||||
|
||||
v0.20
|
||||
-----
|
||||
- Fix build when panel header is not in `/usr/include` (Thanks Vincent Untz).
|
||||
- Fixed build when panel header is not in `/usr/include` (Thanks Vincent Untz).
|
||||
|
||||
v0.19
|
||||
-----
|
||||
- Fix building on Fedora(Unknown `off64_t`) bug #19.
|
||||
- Fixed building on Fedora(Unknown `off64_t`) bug #19.
|
||||
- Use PRNG instead of zero's bug #7. (Thanks xambroz).
|
||||
|
||||
v0.18
|
||||
@@ -81,11 +127,11 @@ v0.17
|
||||
- Remove control reaches end of non-void function" warnings (Thanks Vincent Untz).
|
||||
- Remove unused variables (Thanks Vincent Untz).
|
||||
- Change start key to 'S' instead of F10 (closes debian bug #755474).
|
||||
- Fix problem with unusable device (Closes debian bug #755473).
|
||||
- Fixed problem with unusable device (Closes debian bug #755473).
|
||||
|
||||
v0.16
|
||||
-----
|
||||
- Fix problems building with clang compiler (Thanks Martijn van Brummelen)
|
||||
- Fixed problems building with clang compiler (Thanks Martijn van Brummelen)
|
||||
|
||||
v0.15
|
||||
-----
|
||||
|
||||
81
README.md
81
README.md
@@ -1,10 +1,11 @@
|
||||
# nwipe
|
||||

|
||||

|
||||
[](https://github.com/martijnvanbrummelen/nwipe/releases/)
|
||||
|
||||
nwipe is a program that will securely erase disks. It can operate as both a command line
|
||||
tool without a GUI or with an ncurses GUI as shown in the example below. It can wipe multiple
|
||||
disks simultaneously.
|
||||
nwipe is a program that will securely erase the entire contents of disks. It can operate as both a command line
|
||||
tool without a GUI or with a ncurses GUI as shown in the example below. It can wipe a single drive or multiple
|
||||
disks simultaneously. Nwipe can be found in many Linux distro repositories and the latest version of nwipe is available as a Bootable USB flash image from [here](https://github.com/PartialVolume/shredos.2020.02/blob/master/README.md#obtaining-and-writing-shredos-to-a-usb-flash-drive-the-easy-way-). This can be written to a USB flash drive in seconds, allowing you to boot straight into nwipe.
|
||||
|
||||
The user can select from a variety of recognised secure erase methods which include:
|
||||
|
||||
@@ -22,13 +23,15 @@ It also includes the following pseudo random number generators:
|
||||
* ISAAC
|
||||
|
||||
It is a fork of the dwipe command used by
|
||||
Darik's Boot and Nuke (dban). nwipe is included with [partedmagic](https://partedmagic.com) and
|
||||
[ShredOS](https://github.com/nadenislamarre/shredos) if you want a quick and easy bootable CD or USB version.
|
||||
Darik's Boot and Nuke (dban). nwipe is included with [partedmagic](https://partedmagic.com), [SystemRescueCD](https://www.system-rescue.org), [gparted live](https://sourceforge.net/projects/gparted/files/gparted-live-testing/1.2.0-2/) and
|
||||
[ShredOS](https://github.com/nadenislamarre/shredos)/[ShredOS 2020](https://github.com/PartialVolume/shredos.2020.02) if you want a quick and easy, bootable CD or USB version. If you want a bootable version of the very latest nwipe master that you can write to a USB stick, see [quick and easy bootable version of nwipe master](https://github.com/martijnvanbrummelen/nwipe#quick--easy-usb-bootable-version-of-nwipe-master-for-x86_64-systems)
|
||||
|
||||
Nwipe was created out of a need to run the DBAN dwipe command outside
|
||||
of DBAN, in order to allow its use with any host distribution, thus
|
||||
giving better hardware support.
|
||||
|
||||
The example below shows six drives being simultaneously erased. The video skips to the completion of all six wipes and shows five drives that were successfully erased and one drive that failed due to a I/O error. The drive that failed would then normally be physically destroyed. The five drives that were successfully wiped with zero errors or failures can then be redeployed.
|
||||
|
||||

|
||||
|
||||
## Compiling & Installing
|
||||
@@ -39,6 +42,12 @@ giving better hardware support.
|
||||
* pthreads
|
||||
* parted
|
||||
|
||||
and optionally, but recommended!, the following programs:
|
||||
|
||||
* dmidecode
|
||||
* readlink
|
||||
* smartmontools
|
||||
|
||||
### Debian & Ubuntu prerequisites
|
||||
|
||||
If you are compiling `nwipe` from source, the following libraries will need to be installed first:
|
||||
@@ -51,7 +60,9 @@ sudo apt install \
|
||||
libncurses5-dev \
|
||||
autotools-dev \
|
||||
libparted-dev \
|
||||
dmidecode
|
||||
dmidecode \
|
||||
coreutils \
|
||||
smartmontools
|
||||
```
|
||||
|
||||
### Fedora prerequisites
|
||||
@@ -64,8 +75,22 @@ dnf groupinstall "C Development Tools and Libraries"
|
||||
yum install ncurses-devel
|
||||
yum install parted-devel
|
||||
yum install dmidecode
|
||||
yum install coreutils
|
||||
yum install smartmontools
|
||||
```
|
||||
Note. dmidecode is optional, it provides SMBIOS/DMI host data to stdout or the log file.
|
||||
Note. The following programs are optionally installed although recommended. 1. dmidecode 2. readlink 3. smartmontools.
|
||||
|
||||
#### dmidecode
|
||||
dmidecode provides SMBIOS/DMI host data to stdout or the log file. If you don't install it you won't see the SMBIOS/DMI host data at the beginning of nwipes log.
|
||||
|
||||
#### coreutils (provides readlink)
|
||||
readlink determines the bus type, i.e. ATA, USB etc. Without it the --nousb option won't work and bus type information will be missing from nwipes selection and wipe windows. The coreutils package is often automatically installed as default in most if not all distros.
|
||||
|
||||
#### smartmontools
|
||||
smartmontools obtains serial number information for supported USB to IDE/SATA adapters. Without it, drives plugged into USB ports will not show serial number information.
|
||||
|
||||
|
||||
If you want a quick and easy way to keep your copy of nwipe running the latest master release of nwipe see this section [automating the download and compilation](https://github.com/martijnvanbrummelen/nwipe#automating-the-download-and-compilation-process-for-debian-based-distros)
|
||||
|
||||
### Compilation
|
||||
|
||||
@@ -73,12 +98,13 @@ For a development setup, see [the hacking section below](#Hacking).
|
||||
|
||||
First create all the autoconf files:
|
||||
```
|
||||
./init.sh
|
||||
./autogen.sh
|
||||
```
|
||||
|
||||
Then compile & install using the following standard commands:
|
||||
```
|
||||
./configure
|
||||
make format (only required if submitting pull requests)
|
||||
make
|
||||
make install
|
||||
```
|
||||
@@ -100,6 +126,7 @@ This can be done using the following compile commands:
|
||||
|
||||
```
|
||||
./configure --prefix=/usr CFLAGS='-O0 -g -Wall -Wextra'
|
||||
make format (necessary if submitting pull requests)
|
||||
make
|
||||
make install
|
||||
```
|
||||
@@ -123,6 +150,44 @@ with all the normal optimisations, using:
|
||||
```
|
||||
./configure --prefix=/usr && make && make install
|
||||
```
|
||||
## Automating the download and compilation process for Debian based distros.
|
||||
|
||||
Here's a script that will do just that!. It will create a directory in your home folder called 'nwipe_master'. It installs all the libraries required to compile the software (build-essential) and all the libraries that nwipe requires (libparted etc). It downloads the latest master copy of nwipe from github. It then compiles the software and then runs the latest nwipe. It doesn't write over the version of nwipe that's installed in the repository (If you had nwipe already installed). To run the latest master version of nwipe manually you would run it like this `sudo ~/nwipe_master/nwipe/src/nwipe`
|
||||
|
||||
You can run the script multiple times, the first time it's run it will install all the libraries, subsequent times it will just say the the libraries are upto date. As it always downloads a fresh copy of the nwipe master from Github, you can always stay up to date. Just run it to get the latest version of nwipe. It takes all of 11 seconds on my I7.
|
||||
|
||||
If you already have nwipe installed from the repository, you need to take care which version you are running. If you typed `nwipe` from any directory it will always run the original repository copy of nwipe. To run the latest nwipe you have to explicitly tell it where the new copy is, e.g in the directory `~/nwipe_master/nwipe/src` . That's why you would run it by typing `sudo ~/nwipe_master/nwipe/src/nwipe` alternatively you could cd to the directory and run it like this:
|
||||
|
||||
```
|
||||
cd ~/nwipe_master/nwipe/src
|
||||
./nwipe
|
||||
```
|
||||
|
||||
Note the ./, that means only look in the current directory for nwipe. if you forgot to type ./ the computer would run the older repository version of nwipe.
|
||||
|
||||
Once you have copied the script below into a file called buildnwipe, you need to give the file execute permissions `chmod +x buildnwipe` before you can run it. [Download script](
|
||||
https://drive.google.com/file/d/1BsQDlMqtEycAgfk9FpG1sxv3jFz5dzNO/view?usp=sharing)
|
||||
```
|
||||
#!/bin/bash
|
||||
cd "$HOME"
|
||||
nwipe_directory="nwipe_master"
|
||||
mkdir $nwipe_directory
|
||||
cd $nwipe_directory
|
||||
sudo apt install build-essential pkg-config automake libncurses5-dev autotools-dev libparted-dev dmidecode readlink smartmontools git
|
||||
rm -rf nwipe
|
||||
git clone https://github.com/martijnvanbrummelen/nwipe.git
|
||||
cd "nwipe"
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
cd "src"
|
||||
sudo ./nwipe
|
||||
```
|
||||
## Quick & Easy, USB bootable version of Nwipe Master for x86_64 systems.
|
||||
If you want to just try out a bootable version of nwipe you can download the ShredOS image that's using the latest version of nwipe master and burn it to a USB stick. Instructions and download can be found [here](https://github.com/PartialVolume/shredos.2020.02/blob/master/README.md#obtaining-and-writing-shredos-to-a-usb-flash-drive-the-easy-way-)
|
||||
|
||||
## Which Linux distro uses the latest Nwipe?
|
||||
See [Repology](https://repology.org/project/nwipe/versions)
|
||||
|
||||
## Bugs
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.64])
|
||||
AC_INIT([nwipe], [0.28], [git@brumit.nl])
|
||||
AC_INIT([nwipe], [0.31], [git@brumit.nl])
|
||||
AM_INIT_AUTOMAKE(foreign subdir-objects)
|
||||
AC_OUTPUT(Makefile src/Makefile man/Makefile)
|
||||
AC_CONFIG_SRCDIR([src/nwipe.c])
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 945 KiB After Width: | Height: | Size: 6.1 MiB |
27
man/nwipe.1
27
man/nwipe.1
@@ -1,4 +1,4 @@
|
||||
.TH NWIPE "1" "March 2020" "nwipe version 0.28" "User Commands"
|
||||
.TH NWIPE "1" "June 2021" "nwipe version 0.31" "User Commands"
|
||||
.SH NAME
|
||||
nwipe \- securely erase disks
|
||||
.SH SYNOPSIS
|
||||
@@ -34,8 +34,22 @@ If no devices have been specified on the command line, starts wiping all
|
||||
devices immediately. If devices have been specified, starts wiping only
|
||||
those specified devices immediately.
|
||||
.TP
|
||||
\fB\-\-sync\fR
|
||||
Open devices in sync mode
|
||||
\fB\-\-autopoweroff\fR
|
||||
Power off system on completion of wipe delayed for for one minute. During
|
||||
this one minute delay you can abort the shutdown by typing sudo shutdown -c
|
||||
.TP
|
||||
\fB\-\-sync\fR=\fINUM\fR
|
||||
Will perform a syn after NUM writes (default: 10000)
|
||||
.IP
|
||||
0 \- fdatasync after the disk is completely written
|
||||
fdatasync errors not detected until completion.
|
||||
0 is not recommended as disk errors may cause nwipe
|
||||
to appear to hang
|
||||
.IP
|
||||
1 \- fdatasync after every write
|
||||
Warning: Lower values will reduce wipe speeds.
|
||||
.IP
|
||||
1000 \- fdatasync after 1000 writes
|
||||
.TP
|
||||
\fB\-\-noblank\fR
|
||||
Do not perform the final blanking pass after the wipe (default is to blank,
|
||||
@@ -47,11 +61,18 @@ Do not wait for a key before exiting (default is to wait).
|
||||
\fB\-\-nosignals\fR
|
||||
Do not allow signals to interrupt a wipe (default is to allow).
|
||||
.TP
|
||||
\fB\-\-nousb\fR
|
||||
Do not show or wipe any USB devices, whether in GUI, --nogui or autonuke
|
||||
mode. (default is to allow USB devices to be shown and wiped).
|
||||
.TP
|
||||
\fB\-\-nogui\fR
|
||||
Do not show the GUI interface. Can only be used with the autonuke option.
|
||||
Nowait option is automatically invoked with the nogui option.
|
||||
SIGUSR1 can be used to retrieve the current wiping statistics.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-verbose\fR
|
||||
Log more messages, useful for debugging.
|
||||
.TP
|
||||
\fB\-\-verify\fR=\fITYPE\fR
|
||||
Whether to perform verification of erasure (default: last)
|
||||
.IP
|
||||
|
||||
@@ -30,8 +30,11 @@ typedef enum nwipe_device_t_ {
|
||||
NWIPE_DEVICE_IDE,
|
||||
NWIPE_DEVICE_SCSI,
|
||||
NWIPE_DEVICE_COMPAQ, // Unimplemented.
|
||||
NWIPE_DEVICE_USB, // Unimplemented.
|
||||
NWIPE_DEVICE_IEEE1394 // Unimplemented.
|
||||
NWIPE_DEVICE_USB,
|
||||
NWIPE_DEVICE_IEEE1394, // Unimplemented.
|
||||
NWIPE_DEVICE_ATA,
|
||||
NWIPE_DEVICE_NVME,
|
||||
NWIPE_DEVICE_VIRT
|
||||
} nwipe_device_t;
|
||||
|
||||
typedef enum nwipe_pass_t_ {
|
||||
@@ -66,6 +69,7 @@ typedef struct nwipe_speedring_t_
|
||||
} nwipe_speedring_t;
|
||||
|
||||
#define NWIPE_DEVICE_LABEL_LENGTH 200
|
||||
#define NWIPE_DEVICE_SIZE_TXT_LENGTH 7
|
||||
|
||||
typedef struct nwipe_context_t_
|
||||
{
|
||||
@@ -85,10 +89,12 @@ typedef struct nwipe_context_t_
|
||||
char* device_name; // The device file name.
|
||||
long long device_size; // The device size in bytes.
|
||||
char* device_size_text; // The device size in a more (human)readable format.
|
||||
char device_size_txt[NWIPE_DEVICE_SIZE_TXT_LENGTH]; // The device size in a more (human)readable format.
|
||||
char* device_model; // The model of the device.
|
||||
char device_label[NWIPE_DEVICE_LABEL_LENGTH]; // The label (name, model, size and serial) of the device.
|
||||
struct stat device_stat; // The device file state from fstat().
|
||||
nwipe_device_t device_type; // Indicates an IDE, SCSI, or Compaq SMART device.
|
||||
nwipe_device_t device_type; // Indicates an IDE, SCSI, or Compaq SMART device in enumerated form (int)
|
||||
char device_type_str[14]; // Indicates an IDE, SCSI, USB etc as per nwipe_device_t but in ascii
|
||||
char device_serial_no[21]; // Serial number(processed, 20 characters plus null termination) of the device.
|
||||
int device_target; // The device target.
|
||||
|
||||
@@ -118,6 +124,11 @@ typedef struct nwipe_context_t_
|
||||
u64 throughput; // Average throughput in bytes per second.
|
||||
u64 verify_errors; // The number of verification errors across all passes.
|
||||
int wipe_status; // Wipe finished = 0, wipe in progress = 1, wipe yet to start = -1.
|
||||
int spinner_idx; // Index into the spinner character array
|
||||
char spinner_character[1]; // The current spinner character
|
||||
double duration; // Duration of the wipe in seconds
|
||||
time_t start_time; // Start time of wipe
|
||||
time_t end_time; // End time of wipe
|
||||
/*
|
||||
* Identity contains the raw serial number of the drive
|
||||
* (where applicable), however, for use within nwipe use the
|
||||
|
||||
453
src/device.c
453
src/device.c
@@ -20,10 +20,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
#include "device.h"
|
||||
#include "method.h"
|
||||
#include "options.h"
|
||||
#include "logging.h"
|
||||
@@ -41,6 +47,8 @@
|
||||
int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount );
|
||||
char* trim( char* str );
|
||||
|
||||
extern int terminate_signal;
|
||||
|
||||
int nwipe_device_scan( nwipe_context_t*** c )
|
||||
{
|
||||
/**
|
||||
@@ -61,6 +69,13 @@ int nwipe_device_scan( nwipe_context_t*** c )
|
||||
{
|
||||
if( check_device( c, dev, dcount ) )
|
||||
dcount++;
|
||||
|
||||
/* Don't bother scanning drives if the terminate signal is active ! as in the case of
|
||||
* the readlink program missing which is required if the --nousb option has been specified */
|
||||
if( terminate_signal == 1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the number of devices that were found. */
|
||||
@@ -98,6 +113,13 @@ int nwipe_device_get( nwipe_context_t*** c, char** devnamelist, int ndevnames )
|
||||
|
||||
if( check_device( c, dev, dcount ) )
|
||||
dcount++;
|
||||
|
||||
/* Don't bother scanning drives if the terminate signal is active ! as in the case of
|
||||
* the readlink program missing which is required if the --nousb option has been specified */
|
||||
if( terminate_signal == 1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the number of devices that were found. */
|
||||
@@ -111,6 +133,11 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
nwipe_context_t* next_device;
|
||||
int fd;
|
||||
int idx;
|
||||
int r;
|
||||
char tmp_serial[21];
|
||||
nwipe_device_t bus;
|
||||
|
||||
bus = 0;
|
||||
|
||||
/* Check whether this drive is on the excluded drive list ? */
|
||||
idx = 0;
|
||||
@@ -123,6 +150,36 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether the user has specified using the --nousb option
|
||||
* that all USB devices should not be displayed or wiped whether
|
||||
* in GUI, --nogui or --autonuke modes */
|
||||
|
||||
if( nwipe_options.nousb )
|
||||
{
|
||||
/* retrieve bus and drive serial number, HOWEVER we are only interested in the bus at this time */
|
||||
r = nwipe_get_device_bus_type_and_serialno( dev->path, &bus, tmp_serial );
|
||||
|
||||
/* See nwipe_get_device_bus_type_and_serialno() function for meaning of these codes */
|
||||
if( r == 0 || ( r >= 3 && r <= 6 ) )
|
||||
{
|
||||
if( bus == NWIPE_DEVICE_USB )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Device %s ignored as per command line option --nousb", dev->path );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( r == 2 )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_NOTICE, "--nousb requires the 'readlink' program, please install readlink", dev->path );
|
||||
terminate_signal = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try opening the device to see if it's valid. Close on completion. */
|
||||
if( !ped_device_open( dev ) )
|
||||
{
|
||||
@@ -149,9 +206,11 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
|
||||
/* Get device information */
|
||||
next_device->device_model = dev->model;
|
||||
remove_ATA_prefix( next_device->device_model );
|
||||
next_device->device_name = dev->path;
|
||||
next_device->device_size = dev->length * dev->sector_size;
|
||||
next_device->device_size_text = ped_unit_format_byte( dev, dev->length * dev->sector_size );
|
||||
Determine_C_B_nomenclature( next_device->device_size, next_device->device_size_txt, NWIPE_DEVICE_SIZE_TXT_LENGTH );
|
||||
next_device->device_size_text = next_device->device_size_txt;
|
||||
next_device->result = -2;
|
||||
|
||||
/* Attempt to get serial number of device. */
|
||||
@@ -175,15 +234,70 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
|
||||
// Terminate the string.
|
||||
next_device->device_serial_no[20] = 0;
|
||||
|
||||
// Remove leading/trailing whitespace from serial number and left justify.
|
||||
trim( (char*) next_device->device_serial_no );
|
||||
|
||||
/* if we couldn't obtain serial number by using the above method .. try this */
|
||||
r = nwipe_get_device_bus_type_and_serialno( next_device->device_name, &next_device->device_type, tmp_serial );
|
||||
|
||||
/* If serial number & bus retrieved (0) OR unsupported USB bus identified (5) */
|
||||
if( r == 0 || r == 5 )
|
||||
{
|
||||
/* If the serial number hasn't already been populated */
|
||||
if( next_device->device_serial_no[0] == 0 )
|
||||
{
|
||||
strcpy( next_device->device_serial_no, tmp_serial );
|
||||
}
|
||||
}
|
||||
|
||||
/* All device strings should be 4 characters, prefix with space if under 4 characters */
|
||||
switch( next_device->device_type )
|
||||
{
|
||||
case NWIPE_DEVICE_UNKNOWN:
|
||||
strcpy( next_device->device_type_str, " UNK" );
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_IDE:
|
||||
strcpy( next_device->device_type_str, " IDE" );
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_SCSI:
|
||||
strcpy( next_device->device_type_str, " SCSI" );
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_COMPAQ:
|
||||
strcpy( next_device->device_type_str, " CPQ" );
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_USB:
|
||||
strcpy( next_device->device_type_str, " USB" );
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_IEEE1394:
|
||||
strcpy( next_device->device_type_str, "1394" );
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_ATA:
|
||||
strcpy( next_device->device_type_str, " ATA" );
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_NVME:
|
||||
strcpy( next_device->device_type_str, "NVME" );
|
||||
break;
|
||||
|
||||
case NWIPE_DEVICE_VIRT:
|
||||
strcpy( next_device->device_type_str, "VIRT" );
|
||||
break;
|
||||
}
|
||||
|
||||
if( strlen( (const char*) next_device->device_serial_no ) )
|
||||
{
|
||||
snprintf( next_device->device_label,
|
||||
NWIPE_DEVICE_LABEL_LENGTH,
|
||||
"%s (%s) - %s S/N:%s",
|
||||
"%s %s (%s) %s/%s",
|
||||
next_device->device_name,
|
||||
next_device->device_type_str,
|
||||
next_device->device_size_text,
|
||||
next_device->device_model,
|
||||
next_device->device_serial_no );
|
||||
@@ -192,16 +306,18 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
{
|
||||
snprintf( next_device->device_label,
|
||||
NWIPE_DEVICE_LABEL_LENGTH,
|
||||
"%s (%s) - %s",
|
||||
"%s %s (%s) %s",
|
||||
next_device->device_name,
|
||||
next_device->device_type_str,
|
||||
next_device->device_size_text,
|
||||
next_device->device_model );
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"Found drive model=\"%s\", device path=\"%s\", size=\"%s\", serial number=\"%s\"",
|
||||
next_device->device_model,
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Found %s, %s, %s, %s, S/N=%s",
|
||||
next_device->device_name,
|
||||
next_device->device_type_str,
|
||||
next_device->device_model,
|
||||
next_device->device_size_text,
|
||||
next_device->device_serial_no );
|
||||
|
||||
@@ -261,3 +377,328 @@ char* trim( char* str )
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, char* serialnumber )
|
||||
{
|
||||
/* The caller provides a string that contains the device, i.e. /dev/sdc, also a pointer
|
||||
* to a integer (bus type) and thirdly a 21 byte
|
||||
* character string which this function populates with the serial number (20 characters + null terminator).
|
||||
*
|
||||
* The function populates the bus integer and serial number strings for the given device.
|
||||
* Results for bus would typically be ATA or USB see nwipe_device_t in context.h
|
||||
*
|
||||
* Return Values:
|
||||
* 0 = Success
|
||||
* 1 = popen failed to create stream for readlink
|
||||
* 2 = readlink exit code not 0, see nwipe logs
|
||||
* 3 = popen failed to create stream for smartctl
|
||||
* 4 = smartctl command not found, install smartmontools
|
||||
* 5 = smartctl detected un supported USB to IDE/SATA adapter
|
||||
* 6 = All other errors !
|
||||
*
|
||||
*/
|
||||
|
||||
FILE* fp;
|
||||
|
||||
int r; // A result buffer.
|
||||
int idx_src;
|
||||
int idx_dest;
|
||||
int device_len;
|
||||
int set_return_value;
|
||||
int exit_status;
|
||||
|
||||
char readlink_command[] = "readlink /sys/block/%s";
|
||||
char readlink_command2[] = "/usr/bin/readlink /sys/block/%s";
|
||||
char readlink_command3[] = "/sbin/readlink /sys/block/%s";
|
||||
char smartctl_command[] = "smartctl -i %s";
|
||||
char smartctl_command2[] = "/sbin/smartctl -i %s";
|
||||
char smartctl_command3[] = "/usr/bin/smartctl -i %s";
|
||||
char device_shortform[50];
|
||||
char result[512];
|
||||
char final_cmd_readlink[sizeof( readlink_command ) + sizeof( device_shortform )];
|
||||
char final_cmd_smartctl[sizeof( smartctl_command ) + 256];
|
||||
|
||||
/* Initialise return value */
|
||||
set_return_value = 0;
|
||||
|
||||
*bus = 0;
|
||||
|
||||
/* Scan device name and if device is for instance /dev/sdx then convert to sdx
|
||||
* If already sdx then just copy. */
|
||||
|
||||
idx_dest = 0;
|
||||
device_shortform[idx_dest] = 0;
|
||||
device_len = strlen( device );
|
||||
idx_src = device_len;
|
||||
|
||||
while( idx_src >= 0 )
|
||||
{
|
||||
if( device[idx_src] == '/' || idx_src == 0 )
|
||||
{
|
||||
idx_src++;
|
||||
|
||||
/* Now scan forwards copying the short form device i.e sdc */
|
||||
while( idx_src < device_len )
|
||||
{
|
||||
device_shortform[idx_dest++] = device[idx_src++];
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx_src--;
|
||||
}
|
||||
}
|
||||
device_shortform[idx_dest] = 0;
|
||||
|
||||
final_cmd_readlink[0] = 0;
|
||||
|
||||
/* Determine whether we can access readlink, required if the PATH environment is not setup ! (Debian sid 'su' as
|
||||
* opposed to 'su -' */
|
||||
if( system( "which readlink > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /sbin/readlink > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /usr/bin/readlink > /dev/null 2>&1" ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Command not found. Install readlink !" );
|
||||
set_return_value = 2;
|
||||
|
||||
/* Return immediatley if --nousb specified. Readlink is a requirment for this option. */
|
||||
if( nwipe_options.nousb )
|
||||
{
|
||||
return set_return_value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( final_cmd_readlink, readlink_command3, device_shortform );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( final_cmd_readlink, readlink_command2, device_shortform );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( final_cmd_readlink, readlink_command, device_shortform );
|
||||
}
|
||||
|
||||
if( final_cmd_readlink[0] != 0 )
|
||||
{
|
||||
|
||||
fp = popen( final_cmd_readlink, "r" );
|
||||
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"nwipe_get_device_bus_type_and_serialno: Failed to create stream to %s",
|
||||
readlink_command );
|
||||
|
||||
set_return_value = 1;
|
||||
}
|
||||
|
||||
if( fp != NULL )
|
||||
{
|
||||
/* Read the output a line at a time - output it. */
|
||||
if( fgets( result, sizeof( result ) - 1, fp ) != NULL )
|
||||
{
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
strip_CR_LF( result );
|
||||
nwipe_log( NWIPE_LOG_DEBUG, "Readlink: %s", result );
|
||||
}
|
||||
|
||||
/* Scan the readlink results for bus types, i.e. USB or ATA
|
||||
* Example: readlink
|
||||
* /sys/block/sdd../devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3/2-1.3:1.0/host6/target6:0:0/6:0:0:0/block/sdd
|
||||
*/
|
||||
|
||||
if( strstr( result, "/usb" ) != 0 )
|
||||
{
|
||||
*bus = NWIPE_DEVICE_USB;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strstr( result, "/ata" ) != 0 )
|
||||
{
|
||||
*bus = NWIPE_DEVICE_ATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strstr( result, "/nvme/" ) != 0 )
|
||||
{
|
||||
*bus = NWIPE_DEVICE_NVME;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( strstr( result, "/virtual/" ) != 0 )
|
||||
{
|
||||
*bus = NWIPE_DEVICE_VIRT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* close */
|
||||
r = pclose( fp );
|
||||
|
||||
if( r > 0 )
|
||||
{
|
||||
exit_status = WEXITSTATUS( r );
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"nwipe_get_device_bus_type_and_serialno(): readlink failed, \"%s\" exit status = %u",
|
||||
final_cmd_readlink,
|
||||
exit_status );
|
||||
}
|
||||
|
||||
if( exit_status == 127 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Command not found. Install Readlink recommended !" );
|
||||
set_return_value = 2;
|
||||
if( nwipe_options.nousb )
|
||||
{
|
||||
return set_return_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve smartmontools drive information if USB bridge supports it, so we can retrieve the serial number of the
|
||||
* drive that's on the other side of the USB bridge.. */
|
||||
|
||||
final_cmd_smartctl[0] = 0;
|
||||
|
||||
/* Determine whether we can access smartctl, required if the PATH environment is not setup ! (Debian sid 'su' as
|
||||
* opposed to 'su -' */
|
||||
if( system( "which smartctl > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /sbin/smartctl > /dev/null 2>&1" ) )
|
||||
{
|
||||
if( system( "which /usr/bin/smartctl > /dev/null 2>&1" ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Command not found. Install smartmontools !" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( final_cmd_smartctl, smartctl_command3, device );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( final_cmd_smartctl, smartctl_command2, device );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( final_cmd_smartctl, smartctl_command, device );
|
||||
}
|
||||
|
||||
if( final_cmd_smartctl[0] != 0 )
|
||||
{
|
||||
fp = popen( final_cmd_smartctl, "r" );
|
||||
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"nwipe_get_device_bus_type_and_serialno(): Failed to create stream to %s",
|
||||
smartctl_command );
|
||||
|
||||
set_return_value = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the output a line at a time - output it. */
|
||||
while( fgets( result, sizeof( result ) - 1, fp ) != NULL )
|
||||
{
|
||||
if( nwipe_options.verbose && result[0] != 0x0A )
|
||||
{
|
||||
strip_CR_LF( result );
|
||||
nwipe_log( NWIPE_LOG_DEBUG, "smartctl: %s", result );
|
||||
}
|
||||
|
||||
if( strstr( result, "Serial Number:" ) != 0 )
|
||||
{
|
||||
/* strip any leading or trailing spaces and left justify, +15 is the length of "Serial Number:" */
|
||||
trim( &result[15] );
|
||||
|
||||
strncpy( serialnumber, &result[15], 20 );
|
||||
}
|
||||
}
|
||||
|
||||
/* close */
|
||||
r = pclose( fp );
|
||||
|
||||
if( r > 0 )
|
||||
{
|
||||
exit_status = WEXITSTATUS( r );
|
||||
if( nwipe_options.verbose && exit_status != 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"nwipe_get_device_bus_type_and_serialno(): smartctl failed, \"%s\" exit status = %u",
|
||||
final_cmd_smartctl,
|
||||
exit_status );
|
||||
}
|
||||
set_return_value = 6;
|
||||
|
||||
if( exit_status == 127 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Command not found. Install Smartctl recommended !" );
|
||||
|
||||
set_return_value = 4;
|
||||
}
|
||||
|
||||
if( exit_status == 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "%s USB bridge, no passthru support", device );
|
||||
|
||||
if( *bus == NWIPE_DEVICE_USB )
|
||||
{
|
||||
strcpy( serialnumber, "(no ATA pass thru)" );
|
||||
set_return_value = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return set_return_value;
|
||||
}
|
||||
|
||||
void strip_CR_LF( char* str )
|
||||
{
|
||||
/* In the specified string, replace any CR or LF with a space */
|
||||
int idx = 0;
|
||||
int len = strlen( str );
|
||||
while( idx < len )
|
||||
{
|
||||
if( str[idx] == 0x0A || str[idx] == 0x0D )
|
||||
{
|
||||
str[idx] = ' ';
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void remove_ATA_prefix( char* str )
|
||||
{
|
||||
/* Remove "ATA " prefix if present in the model no. string, left justifing string */
|
||||
|
||||
int idx_pre = 4;
|
||||
int idx_post = 0;
|
||||
|
||||
if( !strncmp( str, "ATA ", 4 ) )
|
||||
{
|
||||
while( str[idx_pre] != 0 )
|
||||
{
|
||||
str[idx_post++] = str[idx_pre++];
|
||||
}
|
||||
|
||||
str[idx_post] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,5 +26,9 @@
|
||||
void nwipe_device_identify( nwipe_context_t* c ); // Get hardware information about the device.
|
||||
int nwipe_device_scan( nwipe_context_t*** c ); // Find devices that we can wipe.
|
||||
int nwipe_device_get( nwipe_context_t*** c, char** devnamelist, int ndevnames ); // Get info about devices to wipe.
|
||||
int nwipe_get_device_bus_type_and_serialno( char*, nwipe_device_t*, char* );
|
||||
void strip_CR_LF( char* );
|
||||
void determine_disk_capacity_nomenclature( u64, char* );
|
||||
void remove_ATA_prefix( char* );
|
||||
|
||||
#endif /* DEVICE_H_ */
|
||||
|
||||
581
src/gui.c
581
src/gui.c
@@ -123,10 +123,24 @@ const char* options_title = " Options ";
|
||||
const char* stats_title = " Statistics ";
|
||||
|
||||
/* Footer labels. */
|
||||
const char* main_window_footer = "S=Start M=Method P=PRNG V=Verify R=Rounds B=Blanking Space=Select Ctrl-C=Quit";
|
||||
const char* selection_footer = "J=Down K=Up Space=Select Backspace=Cancel Ctrl-C=Quit";
|
||||
const char* end_wipe_footer = "B=Blank screen Ctrl-C=Quit";
|
||||
const char* rounds_footer = "Left=Erase Esc=Cancel Ctrl-C=Quit";
|
||||
const char* main_window_footer = "S=Start m=Method p=PRNG v=Verify r=Rounds b=Blanking Space=Select CTRL+C=Quit";
|
||||
const char* main_window_footer_warning_lower_case_s = " WARNING: To start the wipe press SHIFT+S (uppercase S) ";
|
||||
|
||||
const char* main_window_fotter_warning_no_blanking_with_ops2 =
|
||||
" WARNING: Zero blanking is not allowed with ops2 method ";
|
||||
|
||||
const char* main_window_fotter_warning_no_blanking_with_verify_only =
|
||||
" WARNING: Zero blanking is not allowed with verify method ";
|
||||
|
||||
const char* main_window_footer_warning_no_drive_selected =
|
||||
" No drives selected, use spacebar to select a drive, then press S to start ";
|
||||
|
||||
/* Oddly enough, placing extra quotes around the footer strings fixes corruption to the right
|
||||
* of the footer message when the terminal is resized, a quirk in ncurses? - DO NOT REMOVE THE \" */
|
||||
const char* selection_footer = "\"J=Down K=Up Space=Select Backspace=Cancel Ctrl+C=Quit\"";
|
||||
const char* end_wipe_footer = "\"B=Blank screen Ctrl+C=Quit\"";
|
||||
const char* rounds_footer = "\"Left=Erase Esc=Cancel Ctrl+C=Quit\"";
|
||||
|
||||
const char* wipes_finished_footer = "Wipe finished - press enter to exit. Logged to STDOUT";
|
||||
|
||||
/* The number of lines available in the terminal */
|
||||
@@ -213,12 +227,21 @@ void nwipe_gui_init( void )
|
||||
/* Set white on green for success messages. */
|
||||
init_pair( 5, COLOR_WHITE, COLOR_GREEN );
|
||||
|
||||
/* Set white on green for failure messages. */
|
||||
/* Set white on red for failure messages. */
|
||||
init_pair( 6, COLOR_WHITE, COLOR_RED );
|
||||
|
||||
/* Set black on black for when hiding the display. */
|
||||
init_pair( 7, COLOR_BLACK, COLOR_BLACK );
|
||||
|
||||
/* Set green on blue for reverse bold messages */
|
||||
init_pair( 8, COLOR_GREEN, COLOR_WHITE );
|
||||
|
||||
/* Set green on blue for reverse bold error messages */
|
||||
init_pair( 9, COLOR_RED, COLOR_WHITE );
|
||||
|
||||
/* Set black on yellow for warning messages */
|
||||
init_pair( 10, COLOR_BLACK, COLOR_YELLOW );
|
||||
|
||||
/* Set the background style. */
|
||||
wbkgdset( stdscr, COLOR_PAIR( 1 ) | ' ' );
|
||||
}
|
||||
@@ -452,7 +475,7 @@ void nwipe_gui_create_all_windows_on_terminal_resize( const char* footer_text )
|
||||
/* If the user has resized the terminal then recreate the windows and panels */
|
||||
if( stdscr_cols_previous != stdscr_cols || stdscr_lines_previous != stdscr_lines )
|
||||
{
|
||||
/* save the revised terminal size so we check whether the user has resized next time */
|
||||
/* Save the revised terminal size so we check whether the user has resized next time */
|
||||
stdscr_lines_previous = stdscr_lines;
|
||||
stdscr_cols_previous = stdscr_cols;
|
||||
|
||||
@@ -517,7 +540,7 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
int focus = 0;
|
||||
|
||||
/* A generic loop variable. */
|
||||
int i;
|
||||
int i = 0;
|
||||
|
||||
/* User input buffer. */
|
||||
int keystroke;
|
||||
@@ -528,10 +551,16 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
/* Flag, Valid key hit = 1, anything else = 0 */
|
||||
int validkeyhit;
|
||||
|
||||
/* Counts number of drives and partitions that have been selected */
|
||||
int number_of_selected_contexts = 0;
|
||||
|
||||
/* Control A toggle status -1=indefined, 0=all drives delected, 1=all drives selected */
|
||||
int select_all_toggle_status = -1;
|
||||
|
||||
/* Get the terminal size */
|
||||
getmaxyx( stdscr, stdscr_lines, stdscr_cols );
|
||||
|
||||
/* save the terminal size so we check whether the user has resized */
|
||||
/* Save the terminal size so we check whether the user has resized */
|
||||
stdscr_lines_previous = stdscr_lines;
|
||||
stdscr_cols_previous = stdscr_cols;
|
||||
|
||||
@@ -545,6 +574,38 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
|
||||
/* Less two lines for the box and two lines for padding. */
|
||||
slots = wlines - 4;
|
||||
if( slots < 0 )
|
||||
{
|
||||
slots = 0;
|
||||
}
|
||||
|
||||
/* The code here adjusts the offset value, required when the terminal is resized vertically */
|
||||
if( slots > count )
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( focus >= count )
|
||||
{
|
||||
/* The focus is already at the last element. */
|
||||
focus = count - 1;
|
||||
}
|
||||
if( focus < 0 )
|
||||
{
|
||||
/* The focus is already at the last element. */
|
||||
focus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( count >= slots && slots > 0 )
|
||||
{
|
||||
offset = focus + 1 - slots;
|
||||
if( offset < 0 )
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the main window, necessary when switching selections such as method etc */
|
||||
werase( main_window );
|
||||
@@ -595,42 +656,59 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
waddch( main_window, ' ' );
|
||||
}
|
||||
|
||||
switch( c[i + offset]->select )
|
||||
/* In the event for the offset value somehow becoming invalid, this if statement will prevent a segfault
|
||||
* and the else part will log the out of bounds values for debugging */
|
||||
if( i + offset >= 0 && i + offset < count )
|
||||
{
|
||||
case NWIPE_SELECT_TRUE:
|
||||
|
||||
wprintw( main_window, " [wipe] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
|
||||
break;
|
||||
switch( c[i + offset]->select )
|
||||
{
|
||||
case NWIPE_SELECT_TRUE:
|
||||
|
||||
case NWIPE_SELECT_FALSE:
|
||||
/* Print an element that is not selected. */
|
||||
wprintw( main_window, " [ ] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
|
||||
break;
|
||||
wprintw( main_window, " [wipe] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
|
||||
break;
|
||||
|
||||
case NWIPE_SELECT_TRUE_PARENT:
|
||||
case NWIPE_SELECT_FALSE:
|
||||
/* Print an element that is not selected. */
|
||||
wprintw( main_window, " [ ] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
|
||||
break;
|
||||
|
||||
/* This element will be wiped when its parent is wiped. */
|
||||
wprintw( main_window, " [****] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
|
||||
break;
|
||||
case NWIPE_SELECT_TRUE_PARENT:
|
||||
|
||||
case NWIPE_SELECT_FALSE_CHILD:
|
||||
/* This element will be wiped when its parent is wiped. */
|
||||
wprintw( main_window, " [****] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
|
||||
break;
|
||||
|
||||
/* We can't wipe this element because it has a child that is being wiped. */
|
||||
wprintw( main_window, " [----] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
|
||||
break;
|
||||
case NWIPE_SELECT_FALSE_CHILD:
|
||||
|
||||
case NWIPE_SELECT_DISABLED:
|
||||
/* We can't wipe this element because it has a child that is being wiped. */
|
||||
wprintw( main_window, " [----] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
|
||||
break;
|
||||
|
||||
/* We don't know how to wipe this device. (Iomega Zip drives.) */
|
||||
wprintw( main_window, " [????] %s", "Unrecognized Device" );
|
||||
break;
|
||||
case NWIPE_SELECT_DISABLED:
|
||||
|
||||
default:
|
||||
/* We don't know how to wipe this device. (Iomega Zip drives.) */
|
||||
wprintw( main_window, " [????] %s", "Unrecognized Device" );
|
||||
break;
|
||||
|
||||
/* TODO: Handle the sanity error. */
|
||||
break;
|
||||
default:
|
||||
|
||||
} /* switch select */
|
||||
/* TODO: Handle the sanity error. */
|
||||
break;
|
||||
|
||||
} /* switch select */
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_DEBUG,
|
||||
"GUI.c,nwipe_gui_select(), scroll, array index out of bounds, i=%u, count=%u, slots=%u, "
|
||||
"focus=%u, offset=%u",
|
||||
i,
|
||||
count,
|
||||
slots,
|
||||
focus,
|
||||
offset );
|
||||
}
|
||||
|
||||
} /* for */
|
||||
|
||||
@@ -666,20 +744,27 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
* which wastes CPU cycles.
|
||||
*/
|
||||
|
||||
validkeyhit = 0;
|
||||
|
||||
do
|
||||
{
|
||||
validkeyhit = 0;
|
||||
timeout( 250 ); // block getch() for 250ms.
|
||||
keystroke = getch(); // Get user input.
|
||||
timeout( -1 ); // Switch back to blocking mode.
|
||||
|
||||
/* We don't necessarily use all of these. For future reference these are some CTRL+key values
|
||||
* ^A - 1, ^B - 2, ^D - 4, ^E - 5, ^F - 6, ^G - 7, ^H - 8, ^I - 9, ^K - 11, ^L - 12, ^N - 14,
|
||||
* ^O - 15, ^P - 16, ^R - 18, ^T - 20, ^U - 21, ^V - 22, ^W - 23, ^X - 24, ^Y - 25
|
||||
* Use nwipe_log( NWIPE_LOG_DEBUG, "Key Name: %s - %u", keyname(keystroke),keystroke) to
|
||||
* figure out what code is returned by what ever key combination */
|
||||
|
||||
switch( keystroke )
|
||||
{
|
||||
case KEY_DOWN:
|
||||
case 'j':
|
||||
case 'J':
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
/* Increment the focus. */
|
||||
focus += 1;
|
||||
|
||||
@@ -696,7 +781,6 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
offset += 1;
|
||||
break;
|
||||
}
|
||||
validkeyhit = 1;
|
||||
|
||||
break;
|
||||
|
||||
@@ -704,6 +788,8 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
case 'k':
|
||||
case 'K':
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
/* Decrement the focus. */
|
||||
focus -= 1;
|
||||
|
||||
@@ -720,7 +806,6 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
offset -= 1;
|
||||
break;
|
||||
}
|
||||
validkeyhit = 1;
|
||||
|
||||
break;
|
||||
|
||||
@@ -728,6 +813,8 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
case 10:
|
||||
case ' ':
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
/* TODO: This block should be made into a function. */
|
||||
|
||||
if( c[focus]->select == NWIPE_SELECT_TRUE )
|
||||
@@ -794,8 +881,6 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
|
||||
} /* else super-enable */
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
break;
|
||||
|
||||
} /* if NWIPE_SELECT_TRUE */
|
||||
@@ -842,60 +927,196 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
|
||||
} /* else super-deselect */
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
break;
|
||||
|
||||
} /* if NWIPE_SELECT_FALSE */
|
||||
|
||||
/* TODO: Explain to the user why they can't change this. */
|
||||
validkeyhit = 1;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
case 'M':
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
/* Run the method dialog. */
|
||||
nwipe_gui_method();
|
||||
validkeyhit = 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
case 'P':
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
/* Run the PRNG dialog. */
|
||||
nwipe_gui_prng();
|
||||
validkeyhit = 1;
|
||||
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
case 'R':
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
/* Run the rounds dialog. */
|
||||
nwipe_gui_rounds();
|
||||
validkeyhit = 1;
|
||||
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
case 'V':
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
/* Run the option dialog. */
|
||||
nwipe_gui_verify();
|
||||
validkeyhit = 1;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
case 'B':
|
||||
|
||||
validkeyhit = 1;
|
||||
|
||||
if( nwipe_options.method == &nwipe_ops2 )
|
||||
{
|
||||
/* Warn the user about that zero blanking with the ops2 method is not allowed */
|
||||
wattron( footer_window, COLOR_PAIR( 10 ) );
|
||||
nwipe_gui_amend_footer_window( main_window_fotter_warning_no_blanking_with_ops2 );
|
||||
doupdate();
|
||||
sleep( 3 );
|
||||
wattroff( footer_window, COLOR_PAIR( 10 ) );
|
||||
|
||||
/* After the delay return footer text back to key help */
|
||||
nwipe_gui_amend_footer_window( main_window_footer );
|
||||
doupdate();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if( nwipe_options.method == &nwipe_verify )
|
||||
{
|
||||
/* Warn the user about that zero blanking with the ops2 method is not allowed */
|
||||
wattron( footer_window, COLOR_PAIR( 10 ) );
|
||||
nwipe_gui_amend_footer_window( main_window_fotter_warning_no_blanking_with_verify_only );
|
||||
doupdate();
|
||||
sleep( 3 );
|
||||
wattroff( footer_window, COLOR_PAIR( 10 ) );
|
||||
|
||||
/* After the delay return footer text back to key help */
|
||||
nwipe_gui_amend_footer_window( main_window_footer );
|
||||
doupdate();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Run the noblank dialog. */
|
||||
nwipe_gui_noblank();
|
||||
validkeyhit = 1;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
|
||||
/* User want to start the wipe */
|
||||
/* User wants to start the wipe */
|
||||
validkeyhit = 1;
|
||||
|
||||
/* Have any drives have been selected ? */
|
||||
number_of_selected_contexts = 0;
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
if( c[i]->select == NWIPE_SELECT_TRUE )
|
||||
{
|
||||
number_of_selected_contexts += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* if no drives have been selected, print a warning on the footer */
|
||||
if( number_of_selected_contexts == 0 )
|
||||
{
|
||||
wattron( footer_window, COLOR_PAIR( 10 ) );
|
||||
nwipe_gui_amend_footer_window( main_window_footer_warning_no_drive_selected );
|
||||
doupdate();
|
||||
sleep( 3 );
|
||||
wattroff( footer_window, COLOR_PAIR( 10 ) );
|
||||
|
||||
/* After the delay return footer text back to key help */
|
||||
nwipe_gui_amend_footer_window( main_window_footer );
|
||||
doupdate();
|
||||
|
||||
/* Remove any repeated S key strokes, without this the gui would hang
|
||||
* for a period of time, i.e sleep above x number of repeated 's' keystrokes
|
||||
* which could run into minutes */
|
||||
do
|
||||
{
|
||||
timeout( 250 ); // block getch() for 250ms.
|
||||
keystroke = getch(); // Get user input.
|
||||
timeout( -1 ); // Switch back to blocking mode.
|
||||
} while( keystroke == 'S' );
|
||||
|
||||
/* Remove the S from keystroke, which allows us to stay within the selection menu loop */
|
||||
keystroke = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 's':
|
||||
|
||||
/* user has mistakenly hit the lower case 's' instead of capital 'S' */
|
||||
validkeyhit = 1;
|
||||
|
||||
/* Warn the user about their mistake */
|
||||
wattron( footer_window, COLOR_PAIR( 10 ) );
|
||||
nwipe_gui_amend_footer_window( main_window_footer_warning_lower_case_s );
|
||||
doupdate();
|
||||
sleep( 3 );
|
||||
wattroff( footer_window, COLOR_PAIR( 10 ) );
|
||||
|
||||
/* After the delay return footer text back to key help */
|
||||
nwipe_gui_amend_footer_window( main_window_footer );
|
||||
doupdate();
|
||||
|
||||
/* Remove any repeated s key strokes, without this the gui would hang
|
||||
* for a period of time, i.e sleep above x number of repeated 's' keystrokes
|
||||
* which could run into minutes */
|
||||
do
|
||||
{
|
||||
timeout( 250 ); // block getch() for 250ms.
|
||||
keystroke = getch(); // Get user input.
|
||||
timeout( -1 ); // Switch back to blocking mode.
|
||||
} while( keystroke == 's' );
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
/* Ctrl A - Toggle select/deselect all drives */
|
||||
validkeyhit = 1;
|
||||
|
||||
if( select_all_toggle_status == -1 || select_all_toggle_status == 0 )
|
||||
{
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
c[i]->select = NWIPE_SELECT_TRUE;
|
||||
}
|
||||
select_all_toggle_status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( select_all_toggle_status == 1 )
|
||||
{
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
c[i]->select = NWIPE_SELECT_FALSE;
|
||||
}
|
||||
select_all_toggle_status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_ERROR,
|
||||
"gui.c:nwipe_gui_select(), Invalid value in variable select_all_toggle_status = %d",
|
||||
select_all_toggle_status );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} /* keystroke switch */
|
||||
@@ -910,6 +1131,14 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
|
||||
} while( keystroke != 'S' && terminate_signal != 1 );
|
||||
|
||||
if( keystroke == 'S' )
|
||||
{
|
||||
/* If user has pressed S to start wipe change status line */
|
||||
werase( footer_window );
|
||||
nwipe_gui_title( footer_window, end_wipe_footer );
|
||||
wnoutrefresh( footer_window );
|
||||
}
|
||||
|
||||
} /* nwipe_gui_select */
|
||||
|
||||
void nwipe_gui_options( void )
|
||||
@@ -958,6 +1187,13 @@ void nwipe_gui_options( void )
|
||||
} /* switch verify */
|
||||
|
||||
mvwprintw( options_window, NWIPE_GUI_OPTIONS_ROUNDS_Y, NWIPE_GUI_OPTIONS_ROUNDS_X, "Rounds: " );
|
||||
|
||||
/* Disable blanking for ops2 and verify methods */
|
||||
if( nwipe_options.method == &nwipe_ops2 || nwipe_options.method == &nwipe_verify )
|
||||
{
|
||||
nwipe_options.noblank = 1;
|
||||
}
|
||||
|
||||
if( nwipe_options.noblank )
|
||||
{
|
||||
wprintw( options_window, "%i (no final blanking pass)", nwipe_options.rounds );
|
||||
@@ -1631,10 +1867,6 @@ void nwipe_gui_noblank( void )
|
||||
{
|
||||
nwipe_options.noblank = focus;
|
||||
}
|
||||
if( nwipe_options.noblank )
|
||||
{
|
||||
nwipe_options.verify = NWIPE_VERIFY_NONE;
|
||||
}
|
||||
return;
|
||||
|
||||
case KEY_BACKSPACE:
|
||||
@@ -2079,15 +2311,10 @@ void* nwipe_gui_status( void* ptr )
|
||||
nwipe_misc_thread_data = nwipe_thread_data_ptr->nwipe_misc_thread_data;
|
||||
count = nwipe_misc_thread_data->nwipe_selected;
|
||||
|
||||
/* Throughput print formats. */
|
||||
char* nwipe_tera = "%llu TB/s";
|
||||
char* nwipe_giga = "%llu GB/s";
|
||||
char* nwipe_mega = "%llu MB/s";
|
||||
char* nwipe_kilo = "%llu KB/s";
|
||||
char* nwipe_unit = "%llu B/s";
|
||||
char nomenclature_result_str[NOMENCLATURE_RESULT_STR_SIZE]; /* temporary usage */
|
||||
|
||||
/* The throughput format pointer. */
|
||||
char* nwipe_format;
|
||||
/* Spinner character */
|
||||
char spinner_string[2];
|
||||
|
||||
/* We count time from when this function is first called. */
|
||||
static time_t nwipe_time_start = 0;
|
||||
@@ -2143,7 +2370,6 @@ void* nwipe_gui_status( void* ptr )
|
||||
|
||||
/* Throughput variables */
|
||||
u64 nwipe_throughput;
|
||||
u64 nwipe_throughput_stopped;
|
||||
|
||||
/* The number of active wipe processes. */
|
||||
/* Set to 1 initially to start loop. */
|
||||
@@ -2247,7 +2473,7 @@ void* nwipe_gui_status( void* ptr )
|
||||
show_panel( options_panel );
|
||||
show_panel( main_panel );
|
||||
|
||||
/* reprint the footer */
|
||||
/* Reprint the footer */
|
||||
nwipe_gui_title( footer_window, end_wipe_footer );
|
||||
|
||||
// Refresh the footer_window ;
|
||||
@@ -2317,7 +2543,7 @@ void* nwipe_gui_status( void* ptr )
|
||||
case 0x0a:
|
||||
|
||||
/* Check whether we have finished all wipes, if yes exit while loop if user pressed spacebar or
|
||||
* return */
|
||||
* return. */
|
||||
if( !nwipe_active || terminate_signal == 1 )
|
||||
{
|
||||
loop_control = 0;
|
||||
@@ -2333,11 +2559,21 @@ void* nwipe_gui_status( void* ptr )
|
||||
|
||||
} /* keystroke */
|
||||
|
||||
/* If wipe has completed and user has specified auto poweroff or nowait then we can skip waiting for the user to
|
||||
* press return */
|
||||
if( !nwipe_active )
|
||||
{
|
||||
if( nwipe_options.autopoweroff || nwipe_options.nowait )
|
||||
{
|
||||
loop_control = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update screen if not blanked. */
|
||||
if( nwipe_gui_blank == 0 )
|
||||
{
|
||||
|
||||
if( nwipe_active && terminate_signal != 1 )
|
||||
if( terminate_signal != 1 )
|
||||
{
|
||||
nwipe_active = compute_stats( ptr ); // Returns number of active wipe threads
|
||||
}
|
||||
@@ -2355,7 +2591,7 @@ void* nwipe_gui_status( void* ptr )
|
||||
mvwprintw( main_window,
|
||||
yy++,
|
||||
4,
|
||||
"[%05.2f%%, round %i of %i, pass %i of %i] ",
|
||||
"[%5.2f%%, round %i of %i, pass %i of %i] ",
|
||||
c[i]->round_percent,
|
||||
c[i]->round_working,
|
||||
c[i]->round_count,
|
||||
@@ -2371,11 +2607,15 @@ void* nwipe_gui_status( void* ptr )
|
||||
}
|
||||
else if( c[i]->signal )
|
||||
{
|
||||
wattron( main_window, COLOR_PAIR( 9 ) );
|
||||
mvwprintw( main_window, yy++, 4, "(>>> FAILURE! <<<, signal %i) ", c[i]->signal );
|
||||
wattroff( main_window, COLOR_PAIR( 9 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
wattron( main_window, COLOR_PAIR( 9 ) );
|
||||
mvwprintw( main_window, yy++, 4, "(>>>FAILURE!<<<, code %i) ", c[i]->result );
|
||||
wattroff( main_window, COLOR_PAIR( 9 ) );
|
||||
}
|
||||
|
||||
} /* child returned */
|
||||
@@ -2388,57 +2628,71 @@ void* nwipe_gui_status( void* ptr )
|
||||
{
|
||||
wprintw( main_window, "[pass errors: %llu] ", c[i]->pass_errors );
|
||||
}
|
||||
|
||||
switch( c[i]->pass_type )
|
||||
if( c[i]->wipe_status == 1 )
|
||||
{
|
||||
case NWIPE_PASS_FINAL_BLANK:
|
||||
wprintw( main_window, "[blanking] " );
|
||||
break;
|
||||
switch( c[i]->pass_type )
|
||||
{
|
||||
/* Each text field in square brackets should be the same number of characters
|
||||
* to retain output in columns */
|
||||
case NWIPE_PASS_FINAL_BLANK:
|
||||
if( !c[i]->sync_status )
|
||||
{
|
||||
wprintw( main_window, "[ blanking] " );
|
||||
}
|
||||
break;
|
||||
|
||||
case NWIPE_PASS_FINAL_OPS2:
|
||||
wprintw( main_window, "[OPS-II final] " );
|
||||
break;
|
||||
case NWIPE_PASS_FINAL_OPS2:
|
||||
if( !c[i]->sync_status )
|
||||
{
|
||||
wprintw( main_window, "[OPS2final] " );
|
||||
}
|
||||
break;
|
||||
|
||||
case NWIPE_PASS_WRITE:
|
||||
wprintw( main_window, "[writing] " );
|
||||
break;
|
||||
case NWIPE_PASS_WRITE:
|
||||
if( !c[i]->sync_status )
|
||||
{
|
||||
wprintw( main_window, "[ writing ] " );
|
||||
}
|
||||
break;
|
||||
|
||||
case NWIPE_PASS_VERIFY:
|
||||
wprintw( main_window, "[verifying] " );
|
||||
break;
|
||||
case NWIPE_PASS_VERIFY:
|
||||
if( !c[i]->sync_status )
|
||||
{
|
||||
wprintw( main_window, "[verifying] " );
|
||||
}
|
||||
break;
|
||||
|
||||
case NWIPE_PASS_NONE:
|
||||
break;
|
||||
case NWIPE_PASS_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
if( c[i]->sync_status )
|
||||
{
|
||||
wprintw( main_window, "[ syncing ] " );
|
||||
}
|
||||
}
|
||||
|
||||
if( c[i]->sync_status )
|
||||
{
|
||||
wprintw( main_window, "[syncing] " );
|
||||
}
|
||||
/* Determine throughput nomenclature for this drive and output drives throughput to GUI */
|
||||
Determine_C_B_nomenclature( c[i]->throughput, nomenclature_result_str, NOMENCLATURE_RESULT_STR_SIZE );
|
||||
|
||||
if( c[i]->throughput >= INT64_C( 1000000000000 ) )
|
||||
{
|
||||
wprintw( main_window, "[%llu TB/s] ", c[i]->throughput / INT64_C( 1000000000000 ) );
|
||||
}
|
||||
else if( c[i]->throughput >= INT64_C( 1000000000 ) )
|
||||
{
|
||||
wprintw( main_window, "[%llu GB/s] ", c[i]->throughput / INT64_C( 1000000000 ) );
|
||||
}
|
||||
else if( c[i]->throughput >= INT64_C( 1000000 ) )
|
||||
{
|
||||
wprintw( main_window, "[%llu MB/s] ", c[i]->throughput / INT64_C( 1000000 ) );
|
||||
}
|
||||
else if( c[i]->throughput >= INT64_C( 1000 ) )
|
||||
{
|
||||
wprintw( main_window, "[%llu KB/s] ", c[i]->throughput / INT64_C( 1000 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
wprintw( main_window, "[%llu B/s] ", c[i]->throughput / INT64_C( 1 ) );
|
||||
}
|
||||
wprintw( main_window, "[%s/s] ", nomenclature_result_str );
|
||||
|
||||
/* Insert whitespace. */
|
||||
yy += 1;
|
||||
|
||||
/* Increment the next spinner character for this context if the thread is active */
|
||||
if( c[i]->wipe_status == 1 )
|
||||
{
|
||||
spinner( c, i );
|
||||
spinner_string[0] = c[i]->spinner_character[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the wipe thread is no longer active, replace the spinner with a space */
|
||||
spinner_string[0] = ' ';
|
||||
}
|
||||
spinner_string[1] = 0;
|
||||
wprintw( main_window, " %s ", spinner_string );
|
||||
}
|
||||
|
||||
if( offset > 0 )
|
||||
@@ -2463,48 +2717,18 @@ void* nwipe_gui_status( void* ptr )
|
||||
if( nwipe_active && terminate_signal != 1 )
|
||||
{
|
||||
nwipe_gui_load();
|
||||
nwipe_throughput = nwipe_misc_thread_data->throughput;
|
||||
nwipe_throughput_stopped = nwipe_throughput;
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_throughput = nwipe_throughput_stopped;
|
||||
}
|
||||
|
||||
if( nwipe_throughput >= INT64_C( 1000000000000 ) )
|
||||
{
|
||||
nwipe_throughput /= INT64_C( 1000000000000 );
|
||||
nwipe_format = nwipe_tera;
|
||||
}
|
||||
else if( nwipe_throughput >= INT64_C( 1000000000 ) )
|
||||
{
|
||||
nwipe_throughput /= INT64_C( 1000000000 );
|
||||
nwipe_format = nwipe_giga;
|
||||
}
|
||||
else if( nwipe_throughput >= INT64_C( 1000000 ) )
|
||||
{
|
||||
nwipe_throughput /= INT64_C( 1000000 );
|
||||
nwipe_format = nwipe_mega;
|
||||
}
|
||||
else if( nwipe_throughput >= INT64_C( 1000 ) )
|
||||
{
|
||||
nwipe_throughput /= INT64_C( 1000 );
|
||||
nwipe_format = nwipe_kilo;
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_throughput /= INT64_C( 1 );
|
||||
nwipe_format = nwipe_unit;
|
||||
}
|
||||
nwipe_throughput = nwipe_misc_thread_data->throughput;
|
||||
|
||||
/* Determine the nomenclature for the combined throughput */
|
||||
Determine_C_B_nomenclature( nwipe_throughput, nomenclature_result_str, NOMENCLATURE_RESULT_STR_SIZE );
|
||||
|
||||
/* Print the combined throughput. */
|
||||
mvwprintw( stats_window, NWIPE_GUI_STATS_THROUGHPUT_Y, NWIPE_GUI_STATS_THROUGHPUT_X, "Throughput:" );
|
||||
|
||||
if( nwipe_throughput > 0 )
|
||||
{
|
||||
mvwprintw(
|
||||
stats_window, NWIPE_GUI_STATS_THROUGHPUT_Y, NWIPE_GUI_STATS_TAB, nwipe_format, nwipe_throughput );
|
||||
}
|
||||
mvwprintw(
|
||||
stats_window, NWIPE_GUI_STATS_THROUGHPUT_Y, NWIPE_GUI_STATS_TAB, "%s/s", nomenclature_result_str );
|
||||
|
||||
/* Change the current time into a delta. */
|
||||
nwipe_time_now -= nwipe_time_start;
|
||||
@@ -2551,7 +2775,7 @@ void* nwipe_gui_status( void* ptr )
|
||||
/* Print the error count. */
|
||||
mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_ERRORS_X, "Errors:" );
|
||||
mvwprintw(
|
||||
stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_TAB, "%llu", nwipe_misc_thread_data->errors );
|
||||
stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_TAB, " %llu", nwipe_misc_thread_data->errors );
|
||||
|
||||
/* Add a border. */
|
||||
box( stats_window, 0, 0 );
|
||||
@@ -2616,37 +2840,43 @@ int compute_stats( void* ptr )
|
||||
{
|
||||
/* Increment the child counter. */
|
||||
nwipe_active += 1;
|
||||
}
|
||||
|
||||
/* Even if the wipe has finished ALWAYS run the stats one last time so the final SUCCESS percentage value is
|
||||
* correct. Maintain a rolling average of throughput. */
|
||||
nwipe_update_speedring( &c[i]->speedring, c[i]->round_done, nwipe_time_now );
|
||||
/* Even if the wipe has finished ALWAYS run the stats one last time so the final SUCCESS percentage value is
|
||||
* correct. Maintain a rolling average of throughput. */
|
||||
nwipe_update_speedring( &c[i]->speedring, c[i]->round_done, nwipe_time_now );
|
||||
|
||||
if( c[i]->speedring.timestotal > 0 && c[i]->wipe_status == 1 )
|
||||
{
|
||||
/* Update the current average throughput in bytes-per-second. */
|
||||
c[i]->throughput = c[i]->speedring.bytestotal / c[i]->speedring.timestotal;
|
||||
|
||||
/* Update the estimated remaining runtime. */
|
||||
/* Check that throughput is not zero (sometimes caused during a sync) */
|
||||
if( c[i]->throughput == 0 )
|
||||
if( c[i]->speedring.timestotal > 0 && c[i]->wipe_status == 1 )
|
||||
{
|
||||
c[i]->throughput = 1;
|
||||
/* Update the current average throughput in bytes-per-second. */
|
||||
c[i]->throughput = c[i]->speedring.bytestotal / c[i]->speedring.timestotal;
|
||||
|
||||
/* Update the estimated remaining runtime. */
|
||||
/* Check that throughput is not zero (sometimes caused during a sync) */
|
||||
if( c[i]->throughput == 0 )
|
||||
{
|
||||
c[i]->throughput = 1;
|
||||
}
|
||||
|
||||
c[i]->eta = ( c[i]->round_size - c[i]->round_done ) / c[i]->throughput;
|
||||
|
||||
if( c[i]->eta > nwipe_misc_thread_data->maxeta )
|
||||
{
|
||||
nwipe_misc_thread_data->maxeta = c[i]->eta;
|
||||
}
|
||||
}
|
||||
|
||||
c[i]->eta = ( c[i]->round_size - c[i]->round_done ) / c[i]->throughput;
|
||||
|
||||
if( c[i]->eta > nwipe_misc_thread_data->maxeta )
|
||||
{
|
||||
nwipe_misc_thread_data->maxeta = c[i]->eta;
|
||||
}
|
||||
/* Calculate the average throughput */
|
||||
c[i]->throughput = (double) c[i]->round_done / (double) difftime( nwipe_time_now, c[i]->start_time );
|
||||
}
|
||||
|
||||
/* Update the percentage value. */
|
||||
c[i]->round_percent = (double) c[i]->round_done / (double) c[i]->round_size * 100;
|
||||
|
||||
/* Accumulate combined throughput. */
|
||||
nwipe_misc_thread_data->throughput += c[i]->throughput;
|
||||
if( c[i]->wipe_status == 1 )
|
||||
{
|
||||
/* Accumulate combined throughput. */
|
||||
nwipe_misc_thread_data->throughput += c[i]->throughput;
|
||||
}
|
||||
|
||||
/* Accumulate the error count. */
|
||||
nwipe_misc_thread_data->errors += c[i]->pass_errors;
|
||||
@@ -2694,3 +2924,30 @@ void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_bytes,
|
||||
speedring->position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int spinner( nwipe_context_t** ptr, int device_idx )
|
||||
{
|
||||
nwipe_context_t** c;
|
||||
|
||||
c = ptr;
|
||||
|
||||
/* The spinner characters |/-\|/-\ */
|
||||
char sc[9] = "|/-\\|/-\\/";
|
||||
|
||||
/* Check sanity of index */
|
||||
if( c[device_idx]->spinner_idx < 0 || c[device_idx]->spinner_idx > 7 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
c[device_idx]->spinner_character[0] = sc[c[device_idx]->spinner_idx];
|
||||
|
||||
c[device_idx]->spinner_idx++;
|
||||
|
||||
if( c[device_idx]->spinner_idx > 7 )
|
||||
{
|
||||
c[device_idx]->spinner_idx = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,11 @@ void nwipe_gui_prng( void ); // Change the prng option.
|
||||
void nwipe_gui_rounds( void ); // Change the rounds option.
|
||||
void nwipe_gui_verify( void ); // Change the verify option.
|
||||
void nwipe_gui_noblank( void ); // Change the noblank option.
|
||||
int spinner( nwipe_context_t** ptr, int ); // Return the next spinner character
|
||||
|
||||
int compute_stats( void* ptr );
|
||||
void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_done, time_t speedring_now );
|
||||
|
||||
#define NOMENCLATURE_RESULT_STR_SIZE 8
|
||||
|
||||
#endif /* GUI_H_ */
|
||||
|
||||
@@ -16,7 +16,7 @@ MODIFIED:
|
||||
|
||||
#ifndef RAND
|
||||
#define RAND
|
||||
#define RANDSIZL (8) /* I recommend 8 for crypto, 4 for simulations */
|
||||
#define RANDSIZL (4) /* I recommend 8 for crypto, 4 for simulations */
|
||||
#define RANDSIZ (1<<RANDSIZL)
|
||||
|
||||
/* context of random number generator */
|
||||
|
||||
596
src/logging.c
596
src/logging.c
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "stdarg.h"
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
@@ -77,16 +78,22 @@ void nwipe_log( nwipe_log_t level, const char* format, ... )
|
||||
/* Position of writing to current log string */
|
||||
int line_current_pos = 0;
|
||||
|
||||
/* initialise characters written */
|
||||
chars_written = 0;
|
||||
|
||||
/* Print the date. The rc script uses the same format. */
|
||||
chars_written = snprintf( message_buffer,
|
||||
MAX_LOG_LINE_CHARS,
|
||||
"[%i/%02i/%02i %02i:%02i:%02i] nwipe: ",
|
||||
1900 + p->tm_year,
|
||||
1 + p->tm_mon,
|
||||
p->tm_mday,
|
||||
p->tm_hour,
|
||||
p->tm_min,
|
||||
p->tm_sec );
|
||||
if( level != NWIPE_LOG_NOTIMESTAMP )
|
||||
{
|
||||
chars_written = snprintf( message_buffer,
|
||||
MAX_LOG_LINE_CHARS,
|
||||
"[%i/%02i/%02i %02i:%02i:%02i] ",
|
||||
1900 + p->tm_year,
|
||||
1 + p->tm_mon,
|
||||
p->tm_mday,
|
||||
p->tm_hour,
|
||||
p->tm_min,
|
||||
p->tm_sec );
|
||||
}
|
||||
|
||||
/*
|
||||
* Has the end of the buffer been reached ?, snprintf returns the number of characters that would have been
|
||||
@@ -127,22 +134,28 @@ void nwipe_log( nwipe_log_t level, const char* format, ... )
|
||||
{
|
||||
|
||||
case NWIPE_LOG_NONE:
|
||||
case NWIPE_LOG_NOTIMESTAMP:
|
||||
/* Do nothing. */
|
||||
break;
|
||||
|
||||
/* NOTE! The debug labels, i.e. debug, info, notice etc should be left padded with spaces, in order
|
||||
* to maintain column alignment. Pad a label to achieve the length of whatever the longest label happens
|
||||
* to be. Important to know if you are thinking of adding another label.
|
||||
*/
|
||||
|
||||
case NWIPE_LOG_DEBUG:
|
||||
chars_written =
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "debug: " );
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, " debug: " );
|
||||
break;
|
||||
|
||||
case NWIPE_LOG_INFO:
|
||||
chars_written =
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "info: " );
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, " info: " );
|
||||
break;
|
||||
|
||||
case NWIPE_LOG_NOTICE:
|
||||
chars_written =
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "notice: " );
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, " notice: " );
|
||||
break;
|
||||
|
||||
case NWIPE_LOG_WARNING:
|
||||
@@ -152,18 +165,18 @@ void nwipe_log( nwipe_log_t level, const char* format, ... )
|
||||
|
||||
case NWIPE_LOG_ERROR:
|
||||
chars_written =
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "error: " );
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, " error: " );
|
||||
break;
|
||||
|
||||
case NWIPE_LOG_FATAL:
|
||||
chars_written =
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "fatal: " );
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, " fatal: " );
|
||||
break;
|
||||
|
||||
case NWIPE_LOG_SANITY:
|
||||
/* TODO: Request that the user report the log. */
|
||||
chars_written =
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "sanity: " );
|
||||
snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, " sanity: " );
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -391,6 +404,88 @@ void nwipe_perror( int nwipe_errno, const char* f, const char* s )
|
||||
|
||||
} /* nwipe_perror */
|
||||
|
||||
void nwipe_log_OSinfo()
|
||||
{
|
||||
/* Read /proc/version, format and write to the log */
|
||||
|
||||
FILE* fp = NULL;
|
||||
char OS_info_temp[MAX_SIZE_OS_STRING + 1];
|
||||
char OS_info[MAX_SIZE_OS_STRING + 1];
|
||||
int idx;
|
||||
int idx2;
|
||||
int idx3;
|
||||
int idx4;
|
||||
|
||||
/* initialise OS_info & OS_info_temp strings */
|
||||
idx = 0;
|
||||
while( idx < MAX_SIZE_OS_STRING + 1 )
|
||||
{
|
||||
OS_info_temp[idx] = 0;
|
||||
OS_info[idx] = 0;
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Open a pipe to /proc/version for reading */
|
||||
fp = popen( "cat /proc/version", "r" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Unable to create a pipe to /proc/version" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read the OS info */
|
||||
if( fgets( OS_info_temp, MAX_SIZE_OS_STRING, fp ) == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "fget failed to read /proc/version" );
|
||||
fclose( fp );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Format the string for the log, place on multiple lines as necessary,
|
||||
* column aligned, left offset with n (OS_info_Line_offset) spaces */
|
||||
idx = 0;
|
||||
idx2 = 0;
|
||||
idx3 = OS_info_Line_Length;
|
||||
|
||||
while( OS_info_temp[idx] != 0 )
|
||||
{
|
||||
while( idx2 < idx3 && idx2 < MAX_SIZE_OS_STRING )
|
||||
{
|
||||
/* remove newlines from the source */
|
||||
if( OS_info_temp[idx] == 0x0a )
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* copy the character */
|
||||
OS_info[idx2++] = OS_info_temp[idx++];
|
||||
}
|
||||
if( OS_info_temp[idx] != 0 )
|
||||
{
|
||||
OS_info[idx2++] = 0x0a;
|
||||
idx4 = 0;
|
||||
|
||||
/* left indent with spaces */
|
||||
while( idx4 < OS_info_Line_offset && idx2 < MAX_SIZE_OS_STRING )
|
||||
{
|
||||
OS_info[idx2++] = ' ';
|
||||
idx4++;
|
||||
}
|
||||
|
||||
/* calculate idx3 ready for next line */
|
||||
idx3 += OS_info_Line_offset + OS_info_Line_Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s", OS_info );
|
||||
fclose( fp );
|
||||
return;
|
||||
}
|
||||
|
||||
int nwipe_log_sysinfo()
|
||||
{
|
||||
FILE* fp;
|
||||
@@ -429,45 +524,464 @@ int nwipe_log_sysinfo()
|
||||
};
|
||||
|
||||
char dmidecode_command[] = "dmidecode -s %s";
|
||||
char dmidecode_command2[] = "/sbin/dmidecode -s %s";
|
||||
char dmidecode_command3[] = "/usr/bin/dmidecode -s %s";
|
||||
char* p_dmidecode_command;
|
||||
|
||||
char cmd[sizeof( dmidecode_keywords ) + sizeof( dmidecode_command )];
|
||||
char cmd[sizeof( dmidecode_keywords ) + sizeof( dmidecode_command2 )];
|
||||
|
||||
unsigned int keywords_idx;
|
||||
|
||||
keywords_idx = 0;
|
||||
|
||||
/* Run the dmidecode command to retrieve each dmidecode keyword, one at a time */
|
||||
while( dmidecode_keywords[keywords_idx][0] != 0 )
|
||||
p_dmidecode_command = 0;
|
||||
|
||||
if( system( "which dmidecode > /dev/null 2>&1" ) )
|
||||
{
|
||||
sprintf( cmd, dmidecode_command, &dmidecode_keywords[keywords_idx][0] );
|
||||
fp = popen( cmd, "r" );
|
||||
if( fp == NULL )
|
||||
if( system( "which /sbin/dmidecode > /dev/null 2>&1" ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "nwipe_log_sysinfo: Failed to create stream to %s", cmd );
|
||||
return 1;
|
||||
}
|
||||
/* Read the output a line at a time - output it. */
|
||||
while( fgets( path, sizeof( path ) - 1, fp ) != NULL )
|
||||
{
|
||||
/* Remove any trailing return from the string, as nwipe_log automatically adds a return */
|
||||
len = strlen( path );
|
||||
if( path[len - 1] == '\n' )
|
||||
if( system( "which /usr/bin/dmidecode > /dev/null 2>&1" ) )
|
||||
{
|
||||
path[len - 1] = 0;
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Command not found. Install dmidecode !" );
|
||||
}
|
||||
else
|
||||
{
|
||||
p_dmidecode_command = &dmidecode_command3[0];
|
||||
}
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0], path );
|
||||
}
|
||||
/* close */
|
||||
r = pclose( fp );
|
||||
if( r > 0 )
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"nwipe_log_sysinfo(): dmidecode failed, \"%s\" exit status = %u",
|
||||
cmd,
|
||||
WEXITSTATUS( r ) );
|
||||
return 1;
|
||||
p_dmidecode_command = &dmidecode_command2[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p_dmidecode_command = &dmidecode_command[0];
|
||||
}
|
||||
|
||||
if( p_dmidecode_command != 0 )
|
||||
{
|
||||
|
||||
/* Run the dmidecode command to retrieve each dmidecode keyword, one at a time */
|
||||
while( dmidecode_keywords[keywords_idx][0] != 0 )
|
||||
{
|
||||
sprintf( cmd, p_dmidecode_command, &dmidecode_keywords[keywords_idx][0] );
|
||||
fp = popen( cmd, "r" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "nwipe_log_sysinfo: Failed to create stream to %s", cmd );
|
||||
return 1;
|
||||
}
|
||||
/* Read the output a line at a time - output it. */
|
||||
while( fgets( path, sizeof( path ) - 1, fp ) != NULL )
|
||||
{
|
||||
/* Remove any trailing return from the string, as nwipe_log automatically adds a return */
|
||||
len = strlen( path );
|
||||
if( path[len - 1] == '\n' )
|
||||
{
|
||||
path[len - 1] = 0;
|
||||
}
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0], path );
|
||||
}
|
||||
/* close */
|
||||
r = pclose( fp );
|
||||
if( r > 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING,
|
||||
"nwipe_log_sysinfo(): dmidecode failed, \"%s\" exit status = %u",
|
||||
cmd,
|
||||
WEXITSTATUS( r ) );
|
||||
return 1;
|
||||
}
|
||||
keywords_idx++;
|
||||
}
|
||||
keywords_idx++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
|
||||
{
|
||||
/* Prints two summary tables, the first is the device pass and verification summary
|
||||
* and the second is the main summary table detaining the drives, status, throughput,
|
||||
* model and serial number */
|
||||
int i;
|
||||
int idx_src;
|
||||
int idx_dest;
|
||||
char device[7];
|
||||
char status[9];
|
||||
char throughput[13];
|
||||
char total_throughput_string[13];
|
||||
char summary_top_border[256];
|
||||
char summary_top_column_titles[256];
|
||||
char blank[3];
|
||||
char verify[3];
|
||||
// char duration[5];
|
||||
char duration[314];
|
||||
char model[18];
|
||||
char serial_no[20];
|
||||
char exclamation_flag[2];
|
||||
int hours;
|
||||
int minutes;
|
||||
int seconds;
|
||||
u64 total_duration_seconds;
|
||||
u64 total_throughput;
|
||||
nwipe_context_t** c;
|
||||
c = ptr;
|
||||
|
||||
exclamation_flag[0] = 0;
|
||||
device[0] = 0;
|
||||
status[0] = 0;
|
||||
throughput[0] = 0;
|
||||
summary_top_border[0] = 0;
|
||||
summary_top_column_titles[0] = 0;
|
||||
blank[0] = 0;
|
||||
verify[0] = 0;
|
||||
duration[0] = 0;
|
||||
model[0] = 0;
|
||||
serial_no[0] = 0;
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = 0;
|
||||
|
||||
/* A time buffer. */
|
||||
time_t t;
|
||||
|
||||
/* A pointer to the system time struct. */
|
||||
struct tm* p;
|
||||
|
||||
/* Nothing to do, user never started a wipe so no summary table required. */
|
||||
if( global_wipe_status == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print the pass and verifications table */
|
||||
|
||||
/* IMPORTANT: Keep maximum columns (line length) to 80 characters for use with 80x30 terminals, Shredos, ALT-F2 etc
|
||||
* --------------------------------01234567890123456789012345678901234567890123456789012345678901234567890123456789-*/
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "" );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"******************************** Error Summary *********************************" );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "! Device | Pass Errors | Verifications Errors |" );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"--------------------------------------------------------------------------------" );
|
||||
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
{
|
||||
if( c[i]->pass_errors != 0 || c[i]->verify_errors != 0 )
|
||||
{
|
||||
strncpy( exclamation_flag, "!", 1 );
|
||||
exclamation_flag[1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c[i]->wipe_status == 0 )
|
||||
{
|
||||
strncpy( exclamation_flag, " ", 1 );
|
||||
exclamation_flag[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Device name, strip any prefixed /dev/.. leaving up to 6 right justified
|
||||
* characters eg " sda", prefixed with space to 6 characters, note that
|
||||
* we are processing the strings right to left */
|
||||
|
||||
idx_dest = 6;
|
||||
device[idx_dest--] = 0;
|
||||
idx_src = strlen( c[i]->device_name );
|
||||
idx_src--;
|
||||
|
||||
while( idx_dest >= 0 )
|
||||
{
|
||||
/* if the device name contains a / start prefixing spaces */
|
||||
if( c[i]->device_name[idx_src] == '/' )
|
||||
{
|
||||
device[idx_dest--] = ' ';
|
||||
continue;
|
||||
}
|
||||
if( idx_src >= 0 )
|
||||
{
|
||||
device[idx_dest--] = c[i]->device_name[idx_src--];
|
||||
}
|
||||
}
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"%s %s | %10llu | %10llu |",
|
||||
exclamation_flag,
|
||||
device,
|
||||
c[i]->pass_errors,
|
||||
c[i]->verify_errors );
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"********************************************************************************" );
|
||||
|
||||
/* Print the main summary table */
|
||||
|
||||
/* initialise */
|
||||
total_throughput = 0;
|
||||
|
||||
/* Get the current time. */
|
||||
t = time( NULL );
|
||||
p = localtime( &t );
|
||||
/* IMPORTANT: Keep maximum columns (line length) to 80 characters for use with 80x30 terminals, Shredos, ALT-F2 etc
|
||||
* --------------------------------01234567890123456789012345678901234567890123456789012345678901234567890123456789-*/
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "" );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"********************************* Drive Status *********************************" );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "! Device | Status | Thru-put | HH:MM:SS | Model/Serial Number" );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"--------------------------------------------------------------------------------" );
|
||||
/* Example layout:
|
||||
* "! sdv |--FAIL--| 120MB/s | 01:22:01 | WD6788.8488YNHj/ZX677888388-N "
|
||||
* ); " sdv | Erased | 120MB/s | 01:25:04 | WD6784.8488JKGG/ZX677888388-N " ); " sdv | Erased |
|
||||
* 120MB/s | 01:19:07 | WD6788.848HHDDR/ZX677888388-N " ); End of Example layout */
|
||||
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
{
|
||||
/* Device name, strip any prefixed /dev/.. leaving up to 6 right justified
|
||||
* characters eg " sda", prefixed with space to 6 characters, note that
|
||||
* we are processing the strings right to left */
|
||||
|
||||
idx_dest = 6;
|
||||
device[idx_dest--] = 0;
|
||||
idx_src = strlen( c[i]->device_name );
|
||||
idx_src--;
|
||||
|
||||
while( idx_dest >= 0 )
|
||||
{
|
||||
/* if the device name contains a / start prefixing spaces */
|
||||
if( c[i]->device_name[idx_src] == '/' )
|
||||
{
|
||||
device[idx_dest--] = ' ';
|
||||
continue;
|
||||
}
|
||||
if( idx_src >= 0 )
|
||||
{
|
||||
device[idx_dest--] = c[i]->device_name[idx_src--];
|
||||
}
|
||||
}
|
||||
extern int user_abort;
|
||||
|
||||
/* Any errors ? if so set the exclamation_flag and fail message,
|
||||
* All status messages should be eight characters EXACTLY !
|
||||
*/
|
||||
if( c[i]->result < 0 )
|
||||
{
|
||||
strncpy( exclamation_flag, "!", 1 );
|
||||
exclamation_flag[1] = 0;
|
||||
|
||||
strncpy( status, "-FAILED-", 8 );
|
||||
status[8] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if( c[i]->pass_errors != 0 || c[i]->verify_errors != 0 )
|
||||
{
|
||||
strncpy( exclamation_flag, "!", 1 );
|
||||
exclamation_flag[1] = 0;
|
||||
|
||||
strncpy( status, "-FAILED-", 8 );
|
||||
status[8] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c[i]->wipe_status == 0 )
|
||||
{
|
||||
strncpy( exclamation_flag, " ", 1 );
|
||||
exclamation_flag[1] = 0;
|
||||
|
||||
strncpy( status, " Erased ", 8 );
|
||||
status[8] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( user_abort == 1 )
|
||||
{
|
||||
strncpy( exclamation_flag, "!", 1 );
|
||||
exclamation_flag[1] = 0;
|
||||
|
||||
strncpy( status, "UABORTED", 8 );
|
||||
status[8] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If this ever happens, there is a bug ! */
|
||||
strncpy( exclamation_flag, " ", 1 );
|
||||
exclamation_flag[1] = 0;
|
||||
|
||||
strncpy( status, "INSANITY", 8 );
|
||||
status[8] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine the size of throughput so that the correct nomenclature can be used */
|
||||
Determine_C_B_nomenclature( c[i]->throughput, throughput, 13 );
|
||||
|
||||
/* Add this devices throughput to the total throughput */
|
||||
total_throughput += c[i]->throughput;
|
||||
|
||||
/* Retrieve the duration of the wipe in seconds and convert to hours and minutes and seconds */
|
||||
|
||||
if( c[i]->start_time != 0 && c[i]->end_time != 0 )
|
||||
{
|
||||
/* For a summary when the wipe has finished */
|
||||
c[i]->duration = difftime( c[i]->end_time, c[i]->start_time );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c[i]->start_time != 0 && c[i]->end_time == 0 )
|
||||
{
|
||||
/* For a summary in the event of a system shutdown */
|
||||
c[i]->duration = difftime( t, c[i]->start_time );
|
||||
}
|
||||
}
|
||||
|
||||
total_duration_seconds = (u64) c[i]->duration;
|
||||
|
||||
/* Convert binary seconds into three binary variables, hours, minutes and seconds */
|
||||
convert_seconds_to_hours_minutes_seconds( total_duration_seconds, &hours, &minutes, &seconds );
|
||||
|
||||
/* Device Model */
|
||||
strncpy( model, c[i]->device_model, 17 );
|
||||
model[17] = 0;
|
||||
|
||||
/* Serial No. */
|
||||
strncpy( serial_no, c[i]->device_serial_no, 20 );
|
||||
model[17] = 0;
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"%s %s |%s| %s/s | %02i:%02i:%02i | %s/%s",
|
||||
exclamation_flag,
|
||||
device,
|
||||
status,
|
||||
throughput,
|
||||
hours,
|
||||
minutes,
|
||||
seconds,
|
||||
model,
|
||||
serial_no );
|
||||
}
|
||||
|
||||
/* Determine the size of throughput so that the correct nomenclature can be used */
|
||||
Determine_C_B_nomenclature( total_throughput, total_throughput_string, 13 );
|
||||
|
||||
/* Blank abreviations used in summary table B=blank, NB=no blank */
|
||||
if( nwipe_options.noblank )
|
||||
{
|
||||
strcpy( blank, "NB" );
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( blank, "B" );
|
||||
}
|
||||
|
||||
/* Verify abreviations used in summary table */
|
||||
switch( nwipe_options.verify )
|
||||
{
|
||||
case NWIPE_VERIFY_NONE:
|
||||
strcpy( verify, "NV" );
|
||||
break;
|
||||
|
||||
case NWIPE_VERIFY_LAST:
|
||||
strcpy( verify, "VL" );
|
||||
break;
|
||||
|
||||
case NWIPE_VERIFY_ALL:
|
||||
strcpy( verify, "VA" );
|
||||
break;
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"--------------------------------------------------------------------------------" );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"[%i/%02i/%02i %02i:%02i:%02i] Total Throughput %s/s, %s, %iR+%s+%s",
|
||||
1900 + p->tm_year,
|
||||
1 + p->tm_mon,
|
||||
p->tm_mday,
|
||||
p->tm_hour,
|
||||
p->tm_min,
|
||||
p->tm_sec,
|
||||
total_throughput_string,
|
||||
nwipe_method_label( nwipe_options.method ),
|
||||
nwipe_options.rounds,
|
||||
blank,
|
||||
verify );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
|
||||
"********************************************************************************" );
|
||||
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "" );
|
||||
}
|
||||
|
||||
void Determine_C_B_nomenclature( u64 speed, char* result, int result_array_size )
|
||||
{
|
||||
|
||||
/* C_B ? Determine Capacity or Bandwidth nomenclature
|
||||
*
|
||||
* A pointer to a result character string with a minimum of 13 characters in length
|
||||
* should be provided.
|
||||
*
|
||||
* Outputs a string of the form xxxTB/s, xxxGB/s, xxxMB/s, xxxKB/s B/s depending on the value of 'speed'
|
||||
*/
|
||||
|
||||
/* Initialise the output array */
|
||||
int idx = 0;
|
||||
|
||||
while( idx < result_array_size )
|
||||
{
|
||||
result[idx++] = 0;
|
||||
}
|
||||
|
||||
/* Determine the size of throughput so that the correct nomenclature can be used */
|
||||
if( speed >= INT64_C( 1000000000000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu TB", speed / INT64_C( 1000000000000 ) );
|
||||
}
|
||||
else if( speed >= INT64_C( 1000000000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu GB", speed / INT64_C( 1000000000 ) );
|
||||
}
|
||||
else if( speed >= INT64_C( 1000000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu MB", speed / INT64_C( 1000000 ) );
|
||||
}
|
||||
else if( speed >= INT64_C( 1000 ) )
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu KB", speed / INT64_C( 1000 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( result, result_array_size, "%3llu B", speed / INT64_C( 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void convert_seconds_to_hours_minutes_seconds( u64 total_seconds, int* hours, int* minutes, int* seconds )
|
||||
{
|
||||
/* Convert binary seconds into binary hours, minutes and seconds */
|
||||
|
||||
if( total_seconds % 60 )
|
||||
{
|
||||
*minutes = total_seconds / 60;
|
||||
|
||||
*seconds = total_seconds - ( *minutes * 60 );
|
||||
}
|
||||
else
|
||||
{
|
||||
*minutes = total_seconds / 60;
|
||||
|
||||
*seconds = 0;
|
||||
}
|
||||
if( *minutes > 59 )
|
||||
{
|
||||
*hours = *minutes / 60;
|
||||
if( *minutes % 60 )
|
||||
{
|
||||
*minutes = *minutes - ( *hours * 60 );
|
||||
}
|
||||
else
|
||||
{
|
||||
*minutes = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
/* Maximum size of a log message */
|
||||
#define MAX_LOG_LINE_CHARS 512
|
||||
|
||||
#define MAX_SIZE_OS_STRING 512 /* Maximum size of acceptable OS string */
|
||||
#define OS_info_Line_offset 31 /* OS_info line offset in log */
|
||||
#define OS_info_Line_Length 48 /* OS_info line length */
|
||||
|
||||
typedef enum nwipe_log_t_ {
|
||||
NWIPE_LOG_NONE = 0,
|
||||
NWIPE_LOG_DEBUG, // TODO: Very verbose logging.
|
||||
@@ -32,11 +36,16 @@ typedef enum nwipe_log_t_ {
|
||||
NWIPE_LOG_WARNING, // Things that the user should know about.
|
||||
NWIPE_LOG_ERROR, // Non-fatal errors that result in failure.
|
||||
NWIPE_LOG_FATAL, // Errors that cause the program to exit.
|
||||
NWIPE_LOG_SANITY // Programming errors.
|
||||
NWIPE_LOG_SANITY, // Programming errors.
|
||||
NWIPE_LOG_NOTIMESTAMP // logs the message without the timestamp
|
||||
} nwipe_log_t;
|
||||
|
||||
void nwipe_log( nwipe_log_t level, const char* format, ... );
|
||||
void nwipe_perror( int nwipe_errno, const char* f, const char* s );
|
||||
void nwipe_log_OSinfo();
|
||||
int nwipe_log_sysinfo();
|
||||
void nwipe_log_summary( nwipe_context_t**, int ); // This produces the wipe status table on exit
|
||||
void Determine_C_B_nomenclature( u64, char*, int );
|
||||
void convert_seconds_to_hours_minutes_seconds( u64, int*, int*, int* );
|
||||
|
||||
#endif /* LOGGING_H_ */
|
||||
|
||||
475
src/method.c
475
src/method.c
@@ -34,7 +34,7 @@
|
||||
*
|
||||
* WARNING: Never change nwipe_options after calling a method.
|
||||
*
|
||||
* NOTE: The nwipe_runmethod function appends a final pass to all methods.
|
||||
* NOTE: The nwipe_runmethod function appends a user selectable final blanking (zero) pass to all methods.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -123,14 +123,17 @@ void* nwipe_zero( void* ptr )
|
||||
nwipe_context_t* c;
|
||||
c = (nwipe_context_t*) ptr;
|
||||
|
||||
/* get current time at the start of the wipe */
|
||||
time( &c->start_time );
|
||||
|
||||
/* set wipe in progress flag for GUI */
|
||||
c->wipe_status = 1;
|
||||
|
||||
/* setup for a zero-fill. */
|
||||
|
||||
char zerofill[1] = {'\x00'};
|
||||
nwipe_pattern_t patterns[] = {{1, &zerofill[0]}, // pass 1: 0s
|
||||
{0, NULL}};
|
||||
char zerofill[1] = { '\x00' };
|
||||
nwipe_pattern_t patterns[] = { { 1, &zerofill[0] }, // pass 1: 0s
|
||||
{ 0, NULL } };
|
||||
|
||||
/* Run the method. */
|
||||
c->result = nwipe_runmethod( c, patterns );
|
||||
@@ -138,6 +141,9 @@ void* nwipe_zero( void* ptr )
|
||||
/* Finished. Set the wipe_status flag so that the GUI knows */
|
||||
c->wipe_status = 0;
|
||||
|
||||
/* get current time at the end of the wipe */
|
||||
time( &c->end_time );
|
||||
|
||||
return NULL;
|
||||
} /* nwipe_zero */
|
||||
|
||||
@@ -150,11 +156,14 @@ void* nwipe_verify( void* ptr )
|
||||
nwipe_context_t* c;
|
||||
c = (nwipe_context_t*) ptr;
|
||||
|
||||
/* get current time at the start of the wipe */
|
||||
time( &c->start_time );
|
||||
|
||||
/* set wipe in progress flag for GUI */
|
||||
c->wipe_status = 1;
|
||||
|
||||
/* Do nothing because nwipe_runmethod appends a zero-fill. */
|
||||
nwipe_pattern_t patterns[] = {{0, NULL}};
|
||||
nwipe_pattern_t patterns[] = { { 0, NULL } };
|
||||
|
||||
/* Run the method. */
|
||||
c->result = nwipe_runmethod( c, patterns );
|
||||
@@ -162,6 +171,9 @@ void* nwipe_verify( void* ptr )
|
||||
/* Finished. Set the wipe_status flag so that the GUI knows */
|
||||
c->wipe_status = 0;
|
||||
|
||||
/* get current time at the end of the wipe */
|
||||
time( &c->end_time );
|
||||
|
||||
return NULL;
|
||||
} /* nwipe_verify */
|
||||
|
||||
@@ -175,6 +187,9 @@ void* nwipe_dod522022m( void* ptr )
|
||||
nwipe_context_t* c;
|
||||
c = (nwipe_context_t*) ptr;
|
||||
|
||||
/* get current time at the start of the wipe */
|
||||
time( &c->start_time );
|
||||
|
||||
/* set wipe in progress flag for GUI */
|
||||
c->wipe_status = 1;
|
||||
|
||||
@@ -184,14 +199,14 @@ void* nwipe_dod522022m( void* ptr )
|
||||
/* Random characters. (Elements 2 and 6 are unused.) */
|
||||
char dod[7];
|
||||
|
||||
nwipe_pattern_t patterns[] = {{1, &dod[0]}, // Pass 1: A random character.
|
||||
{1, &dod[1]}, // Pass 2: The bitwise complement of pass 1.
|
||||
{-1, ""}, // Pass 3: A random stream.
|
||||
{1, &dod[3]}, // Pass 4: A random character.
|
||||
{1, &dod[4]}, // Pass 5: A random character.
|
||||
{1, &dod[5]}, // Pass 6: The bitwise complement of pass 5.
|
||||
{-1, ""}, // Pass 7: A random stream.
|
||||
{0, NULL}};
|
||||
nwipe_pattern_t patterns[] = { { 1, &dod[0] }, // Pass 1: A random character.
|
||||
{ 1, &dod[1] }, // Pass 2: The bitwise complement of pass 1.
|
||||
{ -1, "" }, // Pass 3: A random stream.
|
||||
{ 1, &dod[3] }, // Pass 4: A random character.
|
||||
{ 1, &dod[4] }, // Pass 5: A random character.
|
||||
{ 1, &dod[5] }, // Pass 6: The bitwise complement of pass 5.
|
||||
{ -1, "" }, // Pass 7: A random stream.
|
||||
{ 0, NULL } };
|
||||
|
||||
/* Load the array with random characters. */
|
||||
r = read( c->entropy_fd, &dod, sizeof( dod ) );
|
||||
@@ -230,6 +245,9 @@ void* nwipe_dod522022m( void* ptr )
|
||||
/* Finished. Set the wipe_status flag so that the GUI knows */
|
||||
c->wipe_status = 0;
|
||||
|
||||
/* get current time at the end of the wipe */
|
||||
time( &c->end_time );
|
||||
|
||||
return NULL;
|
||||
} /* nwipe_dod522022m */
|
||||
|
||||
@@ -244,6 +262,9 @@ void* nwipe_dodshort( void* ptr )
|
||||
nwipe_context_t* c;
|
||||
c = (nwipe_context_t*) ptr;
|
||||
|
||||
/* get current time at the start of the wipe */
|
||||
time( &c->start_time );
|
||||
|
||||
/* set wipe in progress flag for GUI */
|
||||
c->wipe_status = 1;
|
||||
|
||||
@@ -253,10 +274,10 @@ void* nwipe_dodshort( void* ptr )
|
||||
/* Random characters. (Element 3 is unused.) */
|
||||
char dod[3];
|
||||
|
||||
nwipe_pattern_t patterns[] = {{1, &dod[0]}, // Pass 1: A random character.
|
||||
{1, &dod[1]}, // Pass 2: The bitwise complement of pass 1.
|
||||
{-1, ""}, // Pass 3: A random stream.
|
||||
{0, NULL}};
|
||||
nwipe_pattern_t patterns[] = { { 1, &dod[0] }, // Pass 1: A random character.
|
||||
{ 1, &dod[1] }, // Pass 2: The bitwise complement of pass 1.
|
||||
{ -1, "" }, // Pass 3: A random stream.
|
||||
{ 0, NULL } };
|
||||
|
||||
/* Load the array with random characters. */
|
||||
r = read( c->entropy_fd, &dod, sizeof( dod ) );
|
||||
@@ -292,6 +313,9 @@ void* nwipe_dodshort( void* ptr )
|
||||
/* Finished. Set the wipe_status flag so that the GUI knows */
|
||||
c->wipe_status = 0;
|
||||
|
||||
/* get current time at the end of the wipe */
|
||||
time( &c->end_time );
|
||||
|
||||
return NULL;
|
||||
} /* nwipe_dodshort */
|
||||
|
||||
@@ -305,6 +329,9 @@ void* nwipe_gutmann( void* ptr )
|
||||
nwipe_context_t* c;
|
||||
c = (nwipe_context_t*) ptr;
|
||||
|
||||
/* get current time at the start of the wipe */
|
||||
time( &c->start_time );
|
||||
|
||||
/* set wipe in progress flag for GUI */
|
||||
c->wipe_status = 1;
|
||||
|
||||
@@ -321,42 +348,42 @@ void* nwipe_gutmann( void* ptr )
|
||||
int n;
|
||||
|
||||
/* Define the Gutmann method. */
|
||||
nwipe_pattern_t book[] = {{-1, ""}, // Random pass.
|
||||
{-1, ""}, // Random pass.
|
||||
{-1, ""}, // Random pass.
|
||||
{-1, ""}, // Random pass.
|
||||
{3, "\x55\x55\x55"}, // Static pass: 0x555555 01010101 01010101 01010101
|
||||
{3, "\xAA\xAA\xAA"}, // Static pass: 0XAAAAAA 10101010 10101010 10101010
|
||||
{3, "\x92\x49\x24"}, // Static pass: 0x924924 10010010 01001001 00100100
|
||||
{3, "\x49\x24\x92"}, // Static pass: 0x492492 01001001 00100100 10010010
|
||||
{3, "\x24\x92\x49"}, // Static pass: 0x249249 00100100 10010010 01001001
|
||||
{3, "\x00\x00\x00"}, // Static pass: 0x000000 00000000 00000000 00000000
|
||||
{3, "\x11\x11\x11"}, // Static pass: 0x111111 00010001 00010001 00010001
|
||||
{3, "\x22\x22\x22"}, // Static pass: 0x222222 00100010 00100010 00100010
|
||||
{3, "\x33\x33\x33"}, // Static pass: 0x333333 00110011 00110011 00110011
|
||||
{3, "\x44\x44\x44"}, // Static pass: 0x444444 01000100 01000100 01000100
|
||||
{3, "\x55\x55\x55"}, // Static pass: 0x555555 01010101 01010101 01010101
|
||||
{3, "\x66\x66\x66"}, // Static pass: 0x666666 01100110 01100110 01100110
|
||||
{3, "\x77\x77\x77"}, // Static pass: 0x777777 01110111 01110111 01110111
|
||||
{3, "\x88\x88\x88"}, // Static pass: 0x888888 10001000 10001000 10001000
|
||||
{3, "\x99\x99\x99"}, // Static pass: 0x999999 10011001 10011001 10011001
|
||||
{3, "\xAA\xAA\xAA"}, // Static pass: 0xAAAAAA 10101010 10101010 10101010
|
||||
{3, "\xBB\xBB\xBB"}, // Static pass: 0xBBBBBB 10111011 10111011 10111011
|
||||
{3, "\xCC\xCC\xCC"}, // Static pass: 0xCCCCCC 11001100 11001100 11001100
|
||||
{3, "\xDD\xDD\xDD"}, // Static pass: 0xDDDDDD 11011101 11011101 11011101
|
||||
{3, "\xEE\xEE\xEE"}, // Static pass: 0xEEEEEE 11101110 11101110 11101110
|
||||
{3, "\xFF\xFF\xFF"}, // Static pass: 0xFFFFFF 11111111 11111111 11111111
|
||||
{3, "\x92\x49\x24"}, // Static pass: 0x924924 10010010 01001001 00100100
|
||||
{3, "\x49\x24\x92"}, // Static pass: 0x492492 01001001 00100100 10010010
|
||||
{3, "\x24\x92\x49"}, // Static pass: 0x249249 00100100 10010010 01001001
|
||||
{3, "\x6D\xB6\xDB"}, // Static pass: 0x6DB6DB 01101101 10110110 11011011
|
||||
{3, "\xB6\xDB\x6D"}, // Static pass: 0xB6DB6D 10110110 11011011 01101101
|
||||
{3, "\xDB\x6D\xB6"}, // Static pass: 0XDB6DB6 11011011 01101101 10110110
|
||||
{-1, ""}, // Random pass.
|
||||
{-1, ""}, // Random pass.
|
||||
{-1, ""}, // Random pass.
|
||||
{-1, ""}, // Random pass.
|
||||
{0, NULL}};
|
||||
nwipe_pattern_t book[] = { { -1, "" }, // Random pass.
|
||||
{ -1, "" }, // Random pass.
|
||||
{ -1, "" }, // Random pass.
|
||||
{ -1, "" }, // Random pass.
|
||||
{ 3, "\x55\x55\x55" }, // Static pass: 0x555555 01010101 01010101 01010101
|
||||
{ 3, "\xAA\xAA\xAA" }, // Static pass: 0XAAAAAA 10101010 10101010 10101010
|
||||
{ 3, "\x92\x49\x24" }, // Static pass: 0x924924 10010010 01001001 00100100
|
||||
{ 3, "\x49\x24\x92" }, // Static pass: 0x492492 01001001 00100100 10010010
|
||||
{ 3, "\x24\x92\x49" }, // Static pass: 0x249249 00100100 10010010 01001001
|
||||
{ 3, "\x00\x00\x00" }, // Static pass: 0x000000 00000000 00000000 00000000
|
||||
{ 3, "\x11\x11\x11" }, // Static pass: 0x111111 00010001 00010001 00010001
|
||||
{ 3, "\x22\x22\x22" }, // Static pass: 0x222222 00100010 00100010 00100010
|
||||
{ 3, "\x33\x33\x33" }, // Static pass: 0x333333 00110011 00110011 00110011
|
||||
{ 3, "\x44\x44\x44" }, // Static pass: 0x444444 01000100 01000100 01000100
|
||||
{ 3, "\x55\x55\x55" }, // Static pass: 0x555555 01010101 01010101 01010101
|
||||
{ 3, "\x66\x66\x66" }, // Static pass: 0x666666 01100110 01100110 01100110
|
||||
{ 3, "\x77\x77\x77" }, // Static pass: 0x777777 01110111 01110111 01110111
|
||||
{ 3, "\x88\x88\x88" }, // Static pass: 0x888888 10001000 10001000 10001000
|
||||
{ 3, "\x99\x99\x99" }, // Static pass: 0x999999 10011001 10011001 10011001
|
||||
{ 3, "\xAA\xAA\xAA" }, // Static pass: 0xAAAAAA 10101010 10101010 10101010
|
||||
{ 3, "\xBB\xBB\xBB" }, // Static pass: 0xBBBBBB 10111011 10111011 10111011
|
||||
{ 3, "\xCC\xCC\xCC" }, // Static pass: 0xCCCCCC 11001100 11001100 11001100
|
||||
{ 3, "\xDD\xDD\xDD" }, // Static pass: 0xDDDDDD 11011101 11011101 11011101
|
||||
{ 3, "\xEE\xEE\xEE" }, // Static pass: 0xEEEEEE 11101110 11101110 11101110
|
||||
{ 3, "\xFF\xFF\xFF" }, // Static pass: 0xFFFFFF 11111111 11111111 11111111
|
||||
{ 3, "\x92\x49\x24" }, // Static pass: 0x924924 10010010 01001001 00100100
|
||||
{ 3, "\x49\x24\x92" }, // Static pass: 0x492492 01001001 00100100 10010010
|
||||
{ 3, "\x24\x92\x49" }, // Static pass: 0x249249 00100100 10010010 01001001
|
||||
{ 3, "\x6D\xB6\xDB" }, // Static pass: 0x6DB6DB 01101101 10110110 11011011
|
||||
{ 3, "\xB6\xDB\x6D" }, // Static pass: 0xB6DB6D 10110110 11011011 01101101
|
||||
{ 3, "\xDB\x6D\xB6" }, // Static pass: 0XDB6DB6 11011011 01101101 10110110
|
||||
{ -1, "" }, // Random pass.
|
||||
{ -1, "" }, // Random pass.
|
||||
{ -1, "" }, // Random pass.
|
||||
{ -1, "" }, // Random pass.
|
||||
{ 0, NULL } };
|
||||
|
||||
/* Put the book array into this array in random order. */
|
||||
nwipe_pattern_t patterns[36];
|
||||
@@ -412,8 +439,6 @@ void* nwipe_gutmann( void* ptr )
|
||||
|
||||
/* Mark this element as having been used. */
|
||||
book[j].length = 0;
|
||||
|
||||
nwipe_log( NWIPE_LOG_DEBUG, "nwipe_gutmann: Set patterns[%i] = book[%i].", i, j );
|
||||
}
|
||||
|
||||
/* Ensure that the array is terminated. */
|
||||
@@ -426,6 +451,9 @@ void* nwipe_gutmann( void* ptr )
|
||||
/* Finished. Set the wipe_status flag so that the GUI knows */
|
||||
c->wipe_status = 0;
|
||||
|
||||
/* get current time at the end of the wipe */
|
||||
time( &c->end_time );
|
||||
|
||||
return NULL;
|
||||
} /* nwipe_gutmann */
|
||||
|
||||
@@ -443,6 +471,9 @@ void* nwipe_ops2( void* ptr )
|
||||
nwipe_context_t* c;
|
||||
c = (nwipe_context_t*) ptr;
|
||||
|
||||
/* get current time at the start of the wipe */
|
||||
time( &c->start_time );
|
||||
|
||||
/* set wipe in progress flag for GUI */
|
||||
c->wipe_status = 1;
|
||||
|
||||
@@ -588,22 +619,33 @@ void* nwipe_ops2( void* ptr )
|
||||
/* Finished. Set the wipe_status flag so that the GUI knows */
|
||||
c->wipe_status = 0;
|
||||
|
||||
/* get current time at the end of the wipe */
|
||||
time( &c->end_time );
|
||||
|
||||
return NULL;
|
||||
} /* nwipe_ops2 */
|
||||
|
||||
void* nwipe_is5enh( void* ptr )
|
||||
{
|
||||
nwipe_context_t* c = (nwipe_context_t*) ptr;
|
||||
|
||||
/* get current time at the start of the wipe */
|
||||
time( &c->start_time );
|
||||
|
||||
c->wipe_status = 1;
|
||||
|
||||
char is5enh[3] = {'\x00', '\xFF', '\x00'};
|
||||
nwipe_pattern_t patterns[] = {{1, &is5enh[0]}, // Pass 1: 0s
|
||||
{1, &is5enh[1]}, // Pass 2: 1s
|
||||
{-1, &is5enh[2]}, // Pass 3: random bytes with verification
|
||||
{0, NULL}};
|
||||
char is5enh[3] = { '\x00', '\xFF', '\x00' };
|
||||
nwipe_pattern_t patterns[] = { { 1, &is5enh[0] }, // Pass 1: 0s
|
||||
{ 1, &is5enh[1] }, // Pass 2: 1s
|
||||
{ -1, &is5enh[2] }, // Pass 3: random bytes with verification
|
||||
{ 0, NULL } };
|
||||
c->result = nwipe_runmethod( c, patterns );
|
||||
|
||||
c->wipe_status = 0;
|
||||
|
||||
/* get current time at the end of the wipe */
|
||||
time( &c->end_time );
|
||||
|
||||
return NULL;
|
||||
} /* nwipe_is5enh */
|
||||
|
||||
@@ -617,11 +659,14 @@ void* nwipe_random( void* ptr )
|
||||
nwipe_context_t* c;
|
||||
c = (nwipe_context_t*) ptr;
|
||||
|
||||
/* get current time at the start of the wipe */
|
||||
time( &c->start_time );
|
||||
|
||||
/* set wipe in progress flag for GUI */
|
||||
c->wipe_status = 1;
|
||||
|
||||
/* Define the random method. */
|
||||
nwipe_pattern_t patterns[] = {{-1, ""}, {0, NULL}};
|
||||
nwipe_pattern_t patterns[] = { { -1, "" }, { 0, NULL } };
|
||||
|
||||
/* Run the method. */
|
||||
c->result = nwipe_runmethod( c, patterns );
|
||||
@@ -629,6 +674,9 @@ void* nwipe_random( void* ptr )
|
||||
/* Finished. Set the wipe_status flag so that the GUI knows */
|
||||
c->wipe_status = 0;
|
||||
|
||||
/* get current time at the end of the wipe */
|
||||
time( &c->end_time );
|
||||
|
||||
return NULL;
|
||||
} /* nwipe_random */
|
||||
|
||||
@@ -651,7 +699,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
i = 0;
|
||||
|
||||
/* The zero-fill pattern for the final pass of most methods. */
|
||||
nwipe_pattern_t pattern_zero = {1, "\x00"};
|
||||
nwipe_pattern_t pattern_zero = { 1, "\x00" };
|
||||
|
||||
/* Create the PRNG state buffer. */
|
||||
c->prng_seed.length = NWIPE_KNOB_PRNG_STATE_LENGTH;
|
||||
@@ -677,18 +725,6 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
/* Set the number of bytes that will be written across all passes in one round. */
|
||||
c->pass_size = c->pass_count * c->device_size;
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
/* We must read back all passes, so double the byte count. */
|
||||
c->pass_size *= 2;
|
||||
}
|
||||
|
||||
/* Tell the parent the number of rounds that will be run. */
|
||||
c->round_count = nwipe_options.rounds;
|
||||
|
||||
/* Set the initial number of bytes that will be written across all rounds. */
|
||||
c->round_size = c->pass_size;
|
||||
|
||||
/* For the selected method, calculate the correct round_size value (for correct percentage calculation) */
|
||||
calculate_round_size( c );
|
||||
|
||||
@@ -703,21 +739,16 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
/* Initialize the working round counter. */
|
||||
c->round_working = 0;
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Invoking method '%s' on device '%s'.",
|
||||
nwipe_method_label( nwipe_options.method ),
|
||||
c->device_name );
|
||||
nwipe_log(
|
||||
NWIPE_LOG_NOTICE, "Invoking method '%s' on %s", nwipe_method_label( nwipe_options.method ), c->device_name );
|
||||
|
||||
while( c->round_working < c->round_count )
|
||||
{
|
||||
/* Increment the round counter. */
|
||||
c->round_working += 1;
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Starting round %i of %i on device '%s'.",
|
||||
c->round_working,
|
||||
c->round_count,
|
||||
c->device_name );
|
||||
nwipe_log(
|
||||
NWIPE_LOG_NOTICE, "Starting round %i of %i on %s", c->round_working, c->round_count, c->device_name );
|
||||
|
||||
/* Initialize the working pass counter. */
|
||||
c->pass_working = 0;
|
||||
@@ -738,7 +769,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Starting pass %i of %i, round %i of %i, on device '%s'.",
|
||||
"Starting pass %i/%i, round %i/%i, on %s",
|
||||
c->pass_working,
|
||||
c->pass_count,
|
||||
c->round_working,
|
||||
@@ -761,7 +792,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
c->pass_type = NWIPE_PASS_NONE;
|
||||
|
||||
/* Log number of bytes written to disk */
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes written to device '%s'.", c->pass_done, c->device_name );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes written to %s", c->pass_done, c->device_name );
|
||||
|
||||
/* Check for a fatal error. */
|
||||
if( r < 0 )
|
||||
@@ -773,7 +804,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
{
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Verifying pass %i of %i, round %i of %i, on device '%s'.",
|
||||
"Verifying pass %i of %i, round %i of %i, on %s",
|
||||
c->pass_working,
|
||||
c->pass_count,
|
||||
c->round_working,
|
||||
@@ -785,6 +816,8 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
r = nwipe_static_verify( c, &patterns[i] );
|
||||
c->pass_type = NWIPE_PASS_NONE;
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes read from %s", c->pass_done, c->device_name );
|
||||
|
||||
/* Check for a fatal error. */
|
||||
if( r < 0 )
|
||||
{
|
||||
@@ -792,7 +825,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Verified pass %i of %i, round %i of %i, on device '%s'.",
|
||||
"Verified pass %i of %i, round %i of %i, on '%s'.",
|
||||
c->pass_working,
|
||||
c->pass_count,
|
||||
c->round_working,
|
||||
@@ -831,7 +864,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
c->pass_type = NWIPE_PASS_NONE;
|
||||
|
||||
/* Log number of bytes written to disk */
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes written to device '%s'.", c->pass_done, c->device_name );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes written to %s", c->pass_done, c->device_name );
|
||||
|
||||
/* Check for a fatal error. */
|
||||
if( r < 0 )
|
||||
@@ -845,7 +878,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL || lastpass == 1 || nwipe_options.method == &nwipe_is5enh )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Verifying pass %i of %i, round %i of %i, on device '%s'.",
|
||||
"Verifying pass %i of %i, round %i of %i, on %s",
|
||||
c->pass_working,
|
||||
c->pass_count,
|
||||
c->round_working,
|
||||
@@ -857,6 +890,8 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
r = nwipe_random_verify( c );
|
||||
c->pass_type = NWIPE_PASS_NONE;
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes read from %s", c->pass_done, c->device_name );
|
||||
|
||||
/* Check for a fatal error. */
|
||||
if( r < 0 )
|
||||
{
|
||||
@@ -864,7 +899,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Verified pass %i of %i, round %i of %i, on device '%s'.",
|
||||
"Verified pass %i of %i, round %i of %i, on '%s'.",
|
||||
c->pass_working,
|
||||
c->pass_count,
|
||||
c->round_working,
|
||||
@@ -875,7 +910,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
} /* random pass */
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Finished pass %i of %i, round %i of %i, on device '%s'.",
|
||||
"Finished pass %i/%i, round %i/%i, on %s",
|
||||
c->pass_working,
|
||||
c->pass_count,
|
||||
c->round_working,
|
||||
@@ -884,11 +919,19 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
|
||||
} /* for passes */
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Finished round %i of %i on device '%s'.",
|
||||
c->round_working,
|
||||
c->round_count,
|
||||
c->device_name );
|
||||
if( c->round_working < c->round_count )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_NOTICE, "Finished round %i of %i on %s", c->round_working, c->round_count, c->device_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"Finished final round %i of %i on %s",
|
||||
c->round_working,
|
||||
c->round_count,
|
||||
c->device_name );
|
||||
}
|
||||
|
||||
} /* while rounds */
|
||||
|
||||
@@ -923,6 +966,8 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
/* The final ops2 pass. */
|
||||
r = nwipe_random_pass( c );
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes written to %s", c->pass_done, c->device_name );
|
||||
|
||||
/* Check for a fatal error. */
|
||||
if( r < 0 )
|
||||
{
|
||||
@@ -931,27 +976,27 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST || nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Verifying the final random pattern on '%s' is empty.", c->device_name );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Verifying final random pattern FRP on %s", c->device_name );
|
||||
|
||||
/* Verify the final zero pass. */
|
||||
r = nwipe_random_verify( c );
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes read from %s", c->pass_done, c->device_name );
|
||||
|
||||
/* Check for a fatal error. */
|
||||
if( r < 0 )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Verified the final random pattern on '%s' is empty.", c->device_name );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "[SUCCESS] Verified FRP on '%s' matches", c->device_name );
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Wrote final random pattern to '%s'.", c->device_name );
|
||||
|
||||
} /* final ops2 */
|
||||
|
||||
else if( nwipe_options.method == &nwipe_verify )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Verifying that '%s' is empty.", c->device_name );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Verifying that %s is empty", c->device_name );
|
||||
|
||||
/* Verify the final zero pass. */
|
||||
c->pass_type = NWIPE_PASS_VERIFY;
|
||||
@@ -963,8 +1008,14 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Verified that '%s' is empty.", c->device_name );
|
||||
if( c->verify_errors == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "[SUCCESS] Verified that %s is empty.", c->device_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "[FAILURE] %s is not empty .", c->device_name );
|
||||
}
|
||||
|
||||
} /* verify */
|
||||
|
||||
@@ -973,11 +1024,14 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
/* Tell the user that we are on the final pass. */
|
||||
c->pass_type = NWIPE_PASS_FINAL_BLANK;
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Blanking device '%s'.", c->device_name );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Blanking device %s", c->device_name );
|
||||
|
||||
/* The final zero pass. */
|
||||
r = nwipe_static_pass( c, &pattern_zero );
|
||||
|
||||
/* Log number of bytes written to disk */
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes written to %s", c->pass_done, c->device_name );
|
||||
|
||||
/* Check for a fatal error. */
|
||||
if( r < 0 )
|
||||
{
|
||||
@@ -986,10 +1040,15 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST || nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Verifying that '%s' is empty.", c->device_name );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Verifying that %s is empty.", c->device_name );
|
||||
|
||||
/* Verify the final zero pass. */
|
||||
c->pass_type = NWIPE_PASS_VERIFY;
|
||||
r = nwipe_static_verify( c, &pattern_zero );
|
||||
c->pass_type = NWIPE_PASS_NONE;
|
||||
|
||||
/* Log number of bytes read from disk */
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes read from %s", c->pass_done, c->device_name );
|
||||
|
||||
/* Check for a fatal error. */
|
||||
if( r < 0 )
|
||||
@@ -997,10 +1056,24 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
return r;
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Verified that '%s' is empty.", c->device_name );
|
||||
if( c->verify_errors == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "[SUCCESS] Verified that %s is empty.", c->device_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "[FAILURE] %s Verification errors, not empty", c->device_name );
|
||||
}
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Blanked device '%s'.", c->device_name );
|
||||
if( c->verify_errors == 0 && c->pass_errors == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "[SUCCESS] Blanked device %s", c->device_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "[FAILURE] %s may not be blanked", c->device_name );
|
||||
}
|
||||
|
||||
} /* final blank */
|
||||
|
||||
@@ -1014,13 +1087,13 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
if( c->verify_errors > 0 )
|
||||
{
|
||||
/* We finished, but with non-fatal verification errors. */
|
||||
nwipe_log( NWIPE_LOG_ERROR, "%llu verification errors on device '%s'.", c->verify_errors, c->device_name );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "%llu verification errors on '%s'.", c->verify_errors, c->device_name );
|
||||
}
|
||||
|
||||
if( c->pass_errors > 0 )
|
||||
{
|
||||
/* We finished, but with non-fatal wipe errors. */
|
||||
nwipe_log( NWIPE_LOG_ERROR, "%llu wipe errors on device '%s'.", c->pass_errors, c->device_name );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "%llu wipe errors on '%s'.", c->pass_errors, c->device_name );
|
||||
}
|
||||
|
||||
/* FIXME: The 'round_errors' context member is not being used. */
|
||||
@@ -1038,24 +1111,23 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
|
||||
|
||||
void calculate_round_size( nwipe_context_t* c )
|
||||
{
|
||||
/* This is where the round size is adjusted. round_size is used in the running percentage completion
|
||||
/* This is where the round size is calculated. round_size is used in the running percentage completion
|
||||
* calculation. round size is calculated based on pass_size, pass_count, number of rounds, blanking
|
||||
* on/off and verification on/off
|
||||
* on/off and verification All/Last/None
|
||||
*
|
||||
* To hopefully make this adjustment more understandable, I have presented each calculation
|
||||
* under each method. This should make it easier to add a new method here without breaking the
|
||||
* calculations for other methods.
|
||||
* To hopefully make this calculation more understandable, I have separated the calculations that apply to
|
||||
* all methods and processed first then created a switch statement that contains method specific changes if any
|
||||
*/
|
||||
|
||||
/* Don't change the order of these values as the case statements use their index in the array */
|
||||
void* array_methods[] = {&nwipe_zero,
|
||||
&nwipe_ops2,
|
||||
&nwipe_dodshort,
|
||||
&nwipe_dod522022m,
|
||||
&nwipe_gutmann,
|
||||
&nwipe_random,
|
||||
&nwipe_is5enh,
|
||||
NULL};
|
||||
void* array_methods[] = { &nwipe_zero,
|
||||
&nwipe_ops2,
|
||||
&nwipe_dodshort,
|
||||
&nwipe_dod522022m,
|
||||
&nwipe_gutmann,
|
||||
&nwipe_random,
|
||||
&nwipe_is5enh,
|
||||
NULL };
|
||||
int i;
|
||||
|
||||
/* This while loop allows us to effectively create a const so we can use a case statement rather than if statements.
|
||||
@@ -1075,118 +1147,110 @@ void calculate_round_size( nwipe_context_t* c )
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Multiple the round_size by the number of rounds (times) the user wants to wipe the drive with this method.
|
||||
*/
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
/* We must read back all passes, so double the byte count. */
|
||||
c->pass_size *= 2;
|
||||
}
|
||||
|
||||
/* Tell the parent the number of rounds that will be run. */
|
||||
c->round_count = nwipe_options.rounds;
|
||||
|
||||
/* Set the initial number of bytes that will be written across all rounds.
|
||||
c->pass_size includes write AND verification passes if 'verify_all' is selected
|
||||
but does not include the final blanking pass or the verify_last option */
|
||||
c->round_size = c->pass_size;
|
||||
|
||||
/* Multiple the round_size by the number of rounds (times) the user wants to wipe the drive with this method. */
|
||||
c->round_size *= c->round_count;
|
||||
|
||||
/* For each method create the correct round_size value */
|
||||
/* Now increase size based on whether blanking is enabled and verification */
|
||||
if( nwipe_options.noblank == 0 )
|
||||
{
|
||||
/* Blanking enabled so increase round size */
|
||||
c->round_size += c->device_size;
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST || nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Blanking not enabled, check for 'Verify_last', increase round size if enabled. */
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Additional method specific round_size adjustments go in this switch statement */
|
||||
|
||||
switch( selected_method )
|
||||
{
|
||||
case 0:
|
||||
/* NWIPE_ZERO
|
||||
/* NWIPE_ZERO - No additional calculation required
|
||||
* ---------- */
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.noblank == 0 )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* NWIPE_OPS2
|
||||
* ---------- */
|
||||
|
||||
/* Required for the 9th and final random pass */
|
||||
/* Required for mandatory 9th and final random pass */
|
||||
c->round_size += c->device_size;
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
/* Required for selectable 9th and final random verification */
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL || nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
|
||||
/* As no final zero blanking pass is permitted by this standard reduce round size if it's seelected */
|
||||
if( nwipe_options.noblank == 0 )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
/* Reduce for blanking pass */
|
||||
c->round_size -= c->device_size;
|
||||
|
||||
/* Reduce for blanking pass verification */
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL || nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
{
|
||||
c->round_size -= c->device_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
{
|
||||
/* If blanking off & verification on reduce round size */
|
||||
c->round_size -= c->device_size;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* DoD Short
|
||||
/* DoD Short - No additional calculation required
|
||||
* --------- */
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.noblank == 0 )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* DOD 522022m
|
||||
/* DOD 522022m - No additional calculation required
|
||||
* ----------- */
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.noblank == 0 )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/* GutMann
|
||||
/* GutMann - No additional calculation required
|
||||
* ------- */
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.noblank == 0 )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
/* PRNG (random)
|
||||
/* PRNG (random) - No additional calculation required
|
||||
* ------------- */
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
if( nwipe_options.noblank == 0 )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
@@ -1194,25 +1258,20 @@ void calculate_round_size( nwipe_context_t* c )
|
||||
* ------------ */
|
||||
|
||||
/* This method ALWAYS verifies the 3rd pass so increase by device size,
|
||||
* and does not need to be increased by device size for VERIFY_ALL*/
|
||||
* but NOT if VERIFY_ALL has been selected, but first .. */
|
||||
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST )
|
||||
/* Reduce as Verify_Last already included previously if blanking was off */
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_LAST && nwipe_options.noblank == 1 )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
c->round_size -= c->device_size;
|
||||
}
|
||||
if( nwipe_options.verify == NWIPE_VERIFY_ALL )
|
||||
|
||||
/* Adjusts for verify on every third pass multiplied by number of rounds */
|
||||
if( nwipe_options.verify != NWIPE_VERIFY_ALL )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Adjusts for verify on every third pass multiplied by number of rounds */
|
||||
c->round_size += ( c->device_size * c->round_count );
|
||||
}
|
||||
if( nwipe_options.noblank == 0 )
|
||||
{
|
||||
c->round_size += c->device_size;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
477
src/nwipe.c
477
src/nwipe.c
@@ -19,6 +19,10 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE
|
||||
#endif
|
||||
@@ -27,8 +31,7 @@
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <bits/pthreadtypes.h>
|
||||
#include <bits/sigthread.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "nwipe.h"
|
||||
#include "context.h"
|
||||
@@ -45,8 +48,11 @@
|
||||
|
||||
#include <parted/parted.h>
|
||||
#include <parted/debug.h>
|
||||
#include "version.h"
|
||||
|
||||
int terminate_signal;
|
||||
int user_abort;
|
||||
int global_wipe_status;
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
@@ -67,12 +73,28 @@ int main( int argc, char** argv )
|
||||
/* The generic result buffer. */
|
||||
int r;
|
||||
|
||||
/* Log nwipes version */
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s", banner );
|
||||
|
||||
/* Log OS info */
|
||||
nwipe_log_OSinfo();
|
||||
|
||||
/* Initialise the termintaion signal, 1=terminate nwipe */
|
||||
terminate_signal = 0;
|
||||
|
||||
/* Initialise the user abort signal, 1=User aborted with CNTRL-C,SIGTERM, SIGQUIT, SIGINT etc.. */
|
||||
user_abort = 0;
|
||||
|
||||
/* nwipes return status value, set prior to exit at the end of nwipe, as no other exit points allowed */
|
||||
int return_status = 0;
|
||||
|
||||
/* Initialise, flag indicating whether a wipe has actually started or not 0=no, 1=yes */
|
||||
global_wipe_status = 0;
|
||||
|
||||
/* Initialise flags that indicates whether a fatal or non fatal error occured on ANY drive */
|
||||
int fatal_errors_flag = 0;
|
||||
int non_fatal_errors_flag = 0;
|
||||
|
||||
/* Two arrays are used, containing pointers to the the typedef for each disk */
|
||||
/* The first array (c1) points to all devices, the second points to only */
|
||||
/* the disks selected for wiping. */
|
||||
@@ -81,6 +103,8 @@ int main( int argc, char** argv )
|
||||
/* Initialised and populated in device scan. */
|
||||
nwipe_context_t** c1 = 0;
|
||||
|
||||
int wipe_threads_started = 0;
|
||||
|
||||
/* Parse command line options. */
|
||||
nwipe_optind = nwipe_options_parse( argc, argv );
|
||||
if( nwipe_optind == argc )
|
||||
@@ -90,7 +114,8 @@ int main( int argc, char** argv )
|
||||
|
||||
if( nwipe_enumerated == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Storage devices not found." );
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"Storage devices not found. Nwipe should be run as root or sudo/su, i.e sudo nwipe etc" );
|
||||
cleanup();
|
||||
return -1;
|
||||
}
|
||||
@@ -108,12 +133,18 @@ int main( int argc, char** argv )
|
||||
if( nwipe_enumerated == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Devices not found. Check you're not excluding drives unnecessarily." );
|
||||
printf( "No drives found" );
|
||||
printf( "No drives found\n" );
|
||||
cleanup();
|
||||
exit( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( terminate_signal == 1 )
|
||||
{
|
||||
cleanup();
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* Log the System information */
|
||||
nwipe_log_sysinfo();
|
||||
|
||||
@@ -129,6 +160,7 @@ int main( int argc, char** argv )
|
||||
nwipe_perror( errno, __FUNCTION__, "open" );
|
||||
nwipe_log( NWIPE_LOG_FATAL, "Unable to open entropy source %s.", NWIPE_KNOB_ENTROPY );
|
||||
cleanup();
|
||||
free( c2 );
|
||||
return errno;
|
||||
}
|
||||
|
||||
@@ -191,12 +223,6 @@ int main( int argc, char** argv )
|
||||
/* The user must manually select devices. */
|
||||
c1[i]->select = NWIPE_SELECT_FALSE;
|
||||
}
|
||||
|
||||
/* Set the PRNG implementation. */
|
||||
c1[i]->prng = nwipe_options.prng;
|
||||
c1[i]->prng_seed.length = 0;
|
||||
c1[i]->prng_seed.s = 0;
|
||||
c1[i]->prng_state = 0;
|
||||
}
|
||||
|
||||
/* Check for initialization errors. */
|
||||
@@ -232,9 +258,15 @@ int main( int argc, char** argv )
|
||||
}
|
||||
}
|
||||
|
||||
/* Count the number of selected contexts. */
|
||||
for( i = 0; i < nwipe_enumerated; i++ )
|
||||
{
|
||||
/* Set the PRNG implementation, which must always come after the function nwipe_gui_select ! */
|
||||
c1[i]->prng = nwipe_options.prng;
|
||||
c1[i]->prng_seed.length = 0;
|
||||
c1[i]->prng_seed.s = 0;
|
||||
c1[i]->prng_state = 0;
|
||||
|
||||
/* Count the number of selected contexts. */
|
||||
if( c1[i]->select == NWIPE_SELECT_TRUE )
|
||||
{
|
||||
nwipe_selected += 1;
|
||||
@@ -255,150 +287,172 @@ int main( int argc, char** argv )
|
||||
}
|
||||
|
||||
/* TODO: free c1 and c2 memory. */
|
||||
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
if( user_abort == 0 )
|
||||
{
|
||||
/* A result buffer for the BLKGETSIZE64 ioctl. */
|
||||
u64 size64;
|
||||
/* Log the wipe options that have been selected immediately prior to the start of the wipe */
|
||||
nwipe_options_log();
|
||||
|
||||
/* Initialise the wipe_status flag, -1 = wipe not yet started */
|
||||
c2[i]->wipe_status = -1;
|
||||
/* The wipe has been initiated */
|
||||
global_wipe_status = 1;
|
||||
|
||||
/* Open the file for reads and writes. */
|
||||
c2[i]->device_fd = open( c2[i]->device_name, O_RDWR );
|
||||
|
||||
/* Check the open() result. */
|
||||
if( c2[i]->device_fd < 0 )
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "open" );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Unable to open device '%s'.", c2[i]->device_name );
|
||||
c2[i]->select = NWIPE_SELECT_DISABLED;
|
||||
continue;
|
||||
}
|
||||
/* A result buffer for the BLKGETSIZE64 ioctl. */
|
||||
u64 size64;
|
||||
|
||||
/* Stat the file. */
|
||||
if( fstat( c2[i]->device_fd, &c2[i]->device_stat ) != 0 )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "fstat" );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to stat file '%s'.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
continue;
|
||||
}
|
||||
/* Initialise the spinner character index */
|
||||
c2[i]->spinner_idx = 0;
|
||||
|
||||
/* Check that the file is a block device. */
|
||||
if( !S_ISBLK( c2[i]->device_stat.st_mode ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "'%s' is not a block device.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
continue;
|
||||
}
|
||||
/* Initialise the start and end time of the wipe */
|
||||
c2[i]->start_time = 0;
|
||||
c2[i]->end_time = 0;
|
||||
|
||||
/* TODO: Lock the file for exclusive access. */
|
||||
/*
|
||||
if( flock( c2[i]->device_fd, LOCK_EX | LOCK_NB ) != 0 )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "flock" );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to lock the '%s' file.", c2[i]->device_name );
|
||||
/* Initialise the wipe_status flag, -1 = wipe not yet started */
|
||||
c2[i]->wipe_status = -1;
|
||||
|
||||
/* Open the file for reads and writes. */
|
||||
c2[i]->device_fd = open( c2[i]->device_name, O_RDWR );
|
||||
|
||||
/* Check the open() result. */
|
||||
if( c2[i]->device_fd < 0 )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "open" );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Unable to open device '%s'.", c2[i]->device_name );
|
||||
c2[i]->select = NWIPE_SELECT_DISABLED;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Stat the file. */
|
||||
if( fstat( c2[i]->device_fd, &c2[i]->device_stat ) != 0 )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "fstat" );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to stat file '%s'.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* Print serial number of device if it exists. */
|
||||
if( strlen( (const char*) c2[i]->device_serial_no ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Device %s has serial number %s", c2[i]->device_name, c2[i]->device_serial_no );
|
||||
}
|
||||
|
||||
/* Do sector size and block size checking. */
|
||||
if( ioctl( c2[i]->device_fd, BLKSSZGET, &c2[i]->device_sector_size ) == 0 )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_INFO, "Device '%s' has sector size %i.", c2[i]->device_name, c2[i]->device_sector_size );
|
||||
|
||||
if( ioctl( c2[i]->device_fd, BLKBSZGET, &c2[i]->device_block_size ) == 0 )
|
||||
/* Check that the file is a block device. */
|
||||
if( !S_ISBLK( c2[i]->device_stat.st_mode ) )
|
||||
{
|
||||
nwipe_log(
|
||||
NWIPE_LOG_INFO, "Device '%s' has block size %i.", c2[i]->device_name, c2[i]->device_block_size );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "'%s' is not a block device.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* TODO: Lock the file for exclusive access. */
|
||||
/*
|
||||
if( flock( c2[i]->device_fd, LOCK_EX | LOCK_NB ) != 0 )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "flock" );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to lock the '%s' file.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Print serial number of device if it exists. */
|
||||
if( strlen( (const char*) c2[i]->device_serial_no ) )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "%s has serial number %s", c2[i]->device_name, c2[i]->device_serial_no );
|
||||
}
|
||||
|
||||
/* Do sector size and block size checking. */
|
||||
if( ioctl( c2[i]->device_fd, BLKSSZGET, &c2[i]->device_sector_size ) == 0 )
|
||||
{
|
||||
|
||||
if( ioctl( c2[i]->device_fd, BLKBSZGET, &c2[i]->device_block_size ) != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Device '%s' failed BLKBSZGET ioctl.", c2[i]->device_name );
|
||||
c2[i]->device_block_size = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Device '%s' failed BLKBSZGET ioctl.", c2[i]->device_name );
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Device '%s' failed BLKSSZGET ioctl.", c2[i]->device_name );
|
||||
c2[i]->device_sector_size = 0;
|
||||
c2[i]->device_block_size = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "Device '%s' failed BLKSSZGET ioctl.", c2[i]->device_name );
|
||||
c2[i]->device_sector_size = 0;
|
||||
c2[i]->device_block_size = 0;
|
||||
}
|
||||
|
||||
/* The st_size field is zero for block devices. */
|
||||
/* ioctl( c2[i]->device_fd, BLKGETSIZE64, &c2[i]->device_size ); */
|
||||
/* The st_size field is zero for block devices. */
|
||||
/* ioctl( c2[i]->device_fd, BLKGETSIZE64, &c2[i]->device_size ); */
|
||||
|
||||
/* Seek to the end of the device to determine its size. */
|
||||
c2[i]->device_size = lseek( c2[i]->device_fd, 0, SEEK_END );
|
||||
/* Seek to the end of the device to determine its size. */
|
||||
c2[i]->device_size = lseek( c2[i]->device_fd, 0, SEEK_END );
|
||||
|
||||
/* Also ask the driver for the device size. */
|
||||
/* if( ioctl( c2[i]->device_fd, BLKGETSIZE64, &size64 ) ) */
|
||||
if( ioctl( c2[i]->device_fd, _IOR( 0x12, 114, size_t ), &size64 ) )
|
||||
{
|
||||
/* The ioctl failed. */
|
||||
fprintf( stderr, "Error: BLKGETSIZE64 failed on '%s'.\n", c2[i]->device_name );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "BLKGETSIZE64 failed on '%s'.\n", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
}
|
||||
c2[i]->device_size = size64;
|
||||
|
||||
/* Check whether the two size values agree. */
|
||||
if( c2[i]->device_size != size64 )
|
||||
{
|
||||
/* This could be caused by the linux last-odd-block problem. */
|
||||
fprintf( stderr, "Error: Last-odd-block detected on '%s'.\n", c2[i]->device_name );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Last-odd-block detected on '%s'.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
}
|
||||
|
||||
if( c2[i]->device_size == (long long) -1 )
|
||||
{
|
||||
/* We cannot determine the size of this device. */
|
||||
nwipe_perror( errno, __FUNCTION__, "lseek" );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to determine the size of '%s'.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset the file pointer. */
|
||||
r = lseek( c2[i]->device_fd, 0, SEEK_SET );
|
||||
|
||||
if( r == (off64_t) -1 )
|
||||
/* Also ask the driver for the device size. */
|
||||
/* if( ioctl( c2[i]->device_fd, BLKGETSIZE64, &size64 ) ) */
|
||||
if( ioctl( c2[i]->device_fd, _IOR( 0x12, 114, size_t ), &size64 ) )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "lseek" );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to reset the '%s' file offset.", c2[i]->device_name );
|
||||
/* The ioctl failed. */
|
||||
fprintf( stderr, "Error: BLKGETSIZE64 failed on '%s'.\n", c2[i]->device_name );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "BLKGETSIZE64 failed on '%s'.\n", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
}
|
||||
}
|
||||
c2[i]->device_size = size64;
|
||||
|
||||
if( c2[i]->device_size == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Device '%s' is size %llu.", c2[i]->device_name, c2[i]->device_size );
|
||||
nwipe_error++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Device '%s' is size %llu.", c2[i]->device_name, c2[i]->device_size );
|
||||
}
|
||||
/* Check whether the two size values agree. */
|
||||
if( c2[i]->device_size != size64 )
|
||||
{
|
||||
/* This could be caused by the linux last-odd-block problem. */
|
||||
fprintf( stderr, "Error: Last-odd-block detected on '%s'.\n", c2[i]->device_name );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Last-odd-block detected on '%s'.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
}
|
||||
|
||||
/* Fork a child process. */
|
||||
errno = pthread_create( &c2[i]->thread, NULL, nwipe_options.method, (void*) c2[i] );
|
||||
if( errno )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "pthread_create" );
|
||||
if( !nwipe_options.nogui )
|
||||
nwipe_gui_free();
|
||||
return errno;
|
||||
if( c2[i]->device_size == (long long) -1 )
|
||||
{
|
||||
/* We cannot determine the size of this device. */
|
||||
nwipe_perror( errno, __FUNCTION__, "lseek" );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to determine the size of '%s'.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset the file pointer. */
|
||||
r = lseek( c2[i]->device_fd, 0, SEEK_SET );
|
||||
|
||||
if( r == (off64_t) -1 )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "lseek" );
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Unable to reset the '%s' file offset.", c2[i]->device_name );
|
||||
nwipe_error++;
|
||||
}
|
||||
}
|
||||
|
||||
if( c2[i]->device_size == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR,
|
||||
"%s, sect/blk/dev %llu/%i/%llu",
|
||||
c2[i]->device_name,
|
||||
c2[i]->device_sector_size,
|
||||
c2[i]->device_block_size,
|
||||
c2[i]->device_size );
|
||||
nwipe_error++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE,
|
||||
"%s, sect/blk/dev %llu/%i/%llu",
|
||||
c2[i]->device_name,
|
||||
c2[i]->device_sector_size,
|
||||
c2[i]->device_block_size,
|
||||
c2[i]->device_size );
|
||||
}
|
||||
|
||||
/* Fork a child process. */
|
||||
errno = pthread_create( &c2[i]->thread, NULL, nwipe_options.method, (void*) c2[i] );
|
||||
if( errno )
|
||||
{
|
||||
nwipe_perror( errno, __FUNCTION__, "pthread_create" );
|
||||
if( !nwipe_options.nogui )
|
||||
nwipe_gui_free();
|
||||
return errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
wipe_threads_started = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,6 +473,10 @@ int main( int argc, char** argv )
|
||||
}
|
||||
|
||||
/* Wait for all the wiping threads to finish, but don't wait if we receive the terminate signal */
|
||||
|
||||
/* set getch delay to 2/10th second. */
|
||||
halfdelay( 10 );
|
||||
|
||||
i = 0;
|
||||
while( i < nwipe_selected && terminate_signal == 0 )
|
||||
{
|
||||
@@ -436,33 +494,35 @@ int main( int argc, char** argv )
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
sleep( 2 ); /* DO NOT REMOVE ! Stops the routine hogging CPU cycles */
|
||||
sleep( 1 ); /* DO NOT REMOVE ! Stops the routine hogging CPU cycles */
|
||||
}
|
||||
|
||||
if( terminate_signal == 1 )
|
||||
if( terminate_signal != 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Program interrupted" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !nwipe_options.nowait )
|
||||
if( !nwipe_options.nowait && !nwipe_options.autopoweroff )
|
||||
{
|
||||
do
|
||||
{
|
||||
sleep( 1 );
|
||||
|
||||
} while( terminate_signal != 1 );
|
||||
}
|
||||
}
|
||||
nwipe_log( NWIPE_LOG_INFO, "Exit in progress" );
|
||||
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Exit in progress" );
|
||||
}
|
||||
/* Send a REQUEST for the wipe threads to be cancelled */
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
{
|
||||
|
||||
if( c2[i]->thread )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Requesting wipe thread cancellation for %s", c2[i]->device_name );
|
||||
nwipe_log( NWIPE_LOG_INFO, "Please wait.." );
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Requesting wipe thread cancellation for %s", c2[i]->device_name );
|
||||
nwipe_log( NWIPE_LOG_INFO, "Please wait.." );
|
||||
}
|
||||
pthread_cancel( c2[i]->thread );
|
||||
}
|
||||
}
|
||||
@@ -470,7 +530,10 @@ int main( int argc, char** argv )
|
||||
/* Kill the GUI thread */
|
||||
if( nwipe_gui_thread )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Cancelling the GUI thread." );
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Cancelling the GUI thread." );
|
||||
}
|
||||
|
||||
/* We don't want to use pthread_cancel as our GUI thread is aware of the control-c
|
||||
* signal and will exit itself we just join the GUI thread and wait for confirmation
|
||||
@@ -480,7 +543,10 @@ int main( int argc, char** argv )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_WARNING, "main()>pthread_join():Error when waiting for GUI thread to cancel." );
|
||||
}
|
||||
nwipe_log( NWIPE_LOG_INFO, "GUI compute_stats thread has been cancelled" );
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "GUI compute_stats thread has been cancelled" );
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the gui. */
|
||||
@@ -502,39 +568,87 @@ int main( int argc, char** argv )
|
||||
nwipe_log( NWIPE_LOG_WARNING, "main()>pthread_join():Error when waiting for wipe thread to cancel." );
|
||||
}
|
||||
c2[i]->thread = 0; /* Zero the thread so we know it's been cancelled */
|
||||
nwipe_log( NWIPE_LOG_INFO, "Wipe thread for device %s has been cancelled", c2[i]->device_name );
|
||||
|
||||
if( nwipe_options.verbose )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Wipe thread for device %s has been cancelled", c2[i]->device_name );
|
||||
}
|
||||
|
||||
/* Close the device file descriptor. */
|
||||
close( c2[i]->device_fd );
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
/* if no wipe threads started then zero each selected drive result flag,
|
||||
* as we don't need to report fatal/non fatal errors if no wipes were ever started ! */
|
||||
if( wipe_threads_started == 0 )
|
||||
{
|
||||
/* Check for non-fatal errors. */
|
||||
if( c2[i]->result > 0 )
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_FATAL, "Nwipe exited with non fatal errors on device = %s\n", c2[i]->device_name );
|
||||
return_status = 1;
|
||||
c2[i]->result = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
{
|
||||
/* Check for non-fatal errors. */
|
||||
if( c2[i]->result > 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_FATAL, "Nwipe exited with non fatal errors on device = %s\n", c2[i]->device_name );
|
||||
non_fatal_errors_flag = 1;
|
||||
return_status = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
{
|
||||
/* Check for fatal errors. */
|
||||
if( c2[i]->result < 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Nwipe exited with fatal errors on device = %s\n", c2[i]->device_name );
|
||||
fatal_errors_flag = 1;
|
||||
return_status = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < nwipe_selected; i++ )
|
||||
{
|
||||
/* Check for fatal errors. */
|
||||
if( c2[i]->result < 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_ERROR, "Nwipe exited with fatal errors on device = %s\n", c2[i]->device_name );
|
||||
return_status = -1;
|
||||
}
|
||||
}
|
||||
/* Generate and send the drive status summary to the log */
|
||||
nwipe_log_summary( c2, nwipe_selected );
|
||||
|
||||
if( return_status == 0 )
|
||||
/* Print a one line status message for the user */
|
||||
if( return_status == 0 || return_status == 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Nwipe successfully exited." );
|
||||
if( user_abort == 1 )
|
||||
{
|
||||
if( global_wipe_status == 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"Nwipe was aborted by the user. Check the summary table for the drive status." );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Nwipe was aborted by the user prior to the wipe starting." );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fatal_errors_flag == 1 || non_fatal_errors_flag == 1 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"Nwipe exited with errors, check the log & summary table for individual drive status." );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Nwipe successfully completed. See summary table for details." );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup();
|
||||
|
||||
check_for_autopoweroff();
|
||||
|
||||
/* Exit. */
|
||||
return return_status;
|
||||
}
|
||||
@@ -542,6 +656,13 @@ int main( int argc, char** argv )
|
||||
void* signal_hand( void* ptr )
|
||||
{
|
||||
int sig;
|
||||
int hours;
|
||||
int minutes;
|
||||
int seconds;
|
||||
|
||||
hours = 0;
|
||||
minutes = 0;
|
||||
seconds = 0;
|
||||
|
||||
// Define signals that this handler should react to
|
||||
sigset_t sigset;
|
||||
@@ -553,6 +674,7 @@ void* signal_hand( void* ptr )
|
||||
sigaddset( &sigset, SIGUSR1 );
|
||||
|
||||
int i;
|
||||
char eta[9];
|
||||
|
||||
/* Set up the structs we will use for the data required. */
|
||||
nwipe_thread_data_ptr_t* nwipe_thread_data_ptr;
|
||||
@@ -574,7 +696,6 @@ void* signal_hand( void* ptr )
|
||||
|
||||
// Log current status. All values are automatically updated by the GUI
|
||||
case SIGUSR1:
|
||||
{
|
||||
compute_stats( ptr );
|
||||
|
||||
for( i = 0; i < nwipe_misc_thread_data->nwipe_selected; i++ )
|
||||
@@ -608,14 +729,20 @@ void* signal_hand( void* ptr )
|
||||
{
|
||||
status = "[syncing]";
|
||||
}
|
||||
|
||||
convert_seconds_to_hours_minutes_seconds( c[i]->eta, &hours, &minutes, &seconds );
|
||||
|
||||
nwipe_log( NWIPE_LOG_INFO,
|
||||
"%s: %05.2f%%, round %i of %i, pass %i of %i %s",
|
||||
"%s: %05.2f%%, round %i of %i, pass %i of %i, eta %02i:%02i:%02i, %s",
|
||||
c[i]->device_name,
|
||||
c[i]->round_percent,
|
||||
c[i]->round_working,
|
||||
c[i]->round_count,
|
||||
c[i]->pass_working,
|
||||
c[i]->pass_count,
|
||||
hours,
|
||||
minutes,
|
||||
seconds,
|
||||
status );
|
||||
}
|
||||
else
|
||||
@@ -638,21 +765,21 @@ void* signal_hand( void* ptr )
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
case SIGQUIT:
|
||||
case SIGTERM:
|
||||
{
|
||||
/* Set termination flag for main() which will do housekeeping prior to exit */
|
||||
terminate_signal = 1;
|
||||
|
||||
/* Set the user abort flag */
|
||||
user_abort = 1;
|
||||
|
||||
/* Return control to the main thread, returning the signal received */
|
||||
return ( (void*) 0 );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -688,3 +815,21 @@ int cleanup()
|
||||
|
||||
return 0;
|
||||
}
|
||||
void check_for_autopoweroff( void )
|
||||
{
|
||||
char cmd[] = "shutdown -Ph +1 \"System going down in one minute\"";
|
||||
FILE* fp;
|
||||
int r; // A result buffer.
|
||||
|
||||
/* User request auto power down ? */
|
||||
if( nwipe_options.autopoweroff == 1 )
|
||||
{
|
||||
fp = popen( cmd, "r" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_INFO, "Failed to autopoweroff to %s", cmd );
|
||||
return;
|
||||
}
|
||||
r = pclose( fp );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
/* Function prototypes */
|
||||
int cleanup();
|
||||
void check_for_autopoweroff( void );
|
||||
void* signal_hand( void* );
|
||||
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
@@ -66,11 +68,14 @@ int cleanup();
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
/*#include "config.h"*/
|
||||
|
||||
/* System errors. */
|
||||
extern int errno;
|
||||
|
||||
/* 0=wipe not yet started, 1=wipe has been started by the user */
|
||||
extern int global_wipe_status;
|
||||
|
||||
/* Global array to hold log values to print when logging to STDOUT */
|
||||
/* char **log_lines;
|
||||
int log_current_element = 0;
|
||||
@@ -111,6 +116,4 @@ typedef unsigned char u8;
|
||||
/* This is required for ioctl FDFLUSH. */
|
||||
#include <linux/fd.h>
|
||||
|
||||
void* signal_hand( void* );
|
||||
|
||||
#endif /* NWIPE_H_ */
|
||||
|
||||
128
src/options.c
128
src/options.c
@@ -53,65 +53,77 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
int i;
|
||||
|
||||
/* The list of acceptable short options. */
|
||||
char nwipe_options_short[] = "Vhl:m:p:r:e:";
|
||||
char nwipe_options_short[] = "Vvhl:m:p:r:e:";
|
||||
|
||||
/* The list of acceptable long options. */
|
||||
static struct option nwipe_options_long[] = {
|
||||
/* Set when the user wants to wipe without a confirmation prompt. */
|
||||
{"autonuke", no_argument, 0, 0},
|
||||
{ "autonuke", no_argument, 0, 0 },
|
||||
|
||||
/* Set when the user wants to have the system powerdown on completion of wipe. */
|
||||
{ "autopoweroff", no_argument, 0, 0 },
|
||||
|
||||
/* A GNU standard option. Corresponds to the 'h' short option. */
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
|
||||
/* The wipe method. Corresponds to the 'm' short option. */
|
||||
{"method", required_argument, 0, 'm'},
|
||||
{ "method", required_argument, 0, 'm' },
|
||||
|
||||
/* Log file. Corresponds to the 'l' short option. */
|
||||
{"logfile", required_argument, 0, 'l'},
|
||||
{ "logfile", required_argument, 0, 'l' },
|
||||
|
||||
/* Exclude devices, comma separated list */
|
||||
{"exclude", required_argument, 0, 'e'},
|
||||
{ "exclude", required_argument, 0, 'e' },
|
||||
|
||||
/* The Pseudo Random Number Generator. */
|
||||
{"prng", required_argument, 0, 'p'},
|
||||
{ "prng", required_argument, 0, 'p' },
|
||||
|
||||
/* The number of times to run the method. */
|
||||
{"rounds", required_argument, 0, 'r'},
|
||||
{ "rounds", required_argument, 0, 'r' },
|
||||
|
||||
/* Whether to blank the disk after wiping. */
|
||||
{"noblank", no_argument, 0, 0},
|
||||
{ "noblank", no_argument, 0, 0 },
|
||||
|
||||
/* Whether to ignore all USB devices. */
|
||||
{ "nousb", no_argument, 0, 0 },
|
||||
|
||||
/* Whether to exit after wiping or wait for a keypress. */
|
||||
{"nowait", no_argument, 0, 0},
|
||||
{ "nowait", no_argument, 0, 0 },
|
||||
|
||||
/* Whether to allow signals to interrupt a wipe. */
|
||||
{"nosignals", no_argument, 0, 0},
|
||||
{ "nosignals", no_argument, 0, 0 },
|
||||
|
||||
/* Whether to exit after wiping or wait for a keypress. */
|
||||
{"nogui", no_argument, 0, 0},
|
||||
{ "nogui", no_argument, 0, 0 },
|
||||
|
||||
/* A flag to indicate whether the devices whould be opened in sync mode. */
|
||||
{"sync", required_argument, 0, 0},
|
||||
{ "sync", required_argument, 0, 0 },
|
||||
|
||||
/* Verify that wipe patterns are being written to the device. */
|
||||
{"verify", required_argument, 0, 0},
|
||||
{ "verify", required_argument, 0, 0 },
|
||||
|
||||
/* Display program version. */
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{ "verbose", no_argument, 0, 'v' },
|
||||
|
||||
/* Display program version. */
|
||||
{ "version", no_argument, 0, 'V' },
|
||||
|
||||
/* Requisite padding for getopt(). */
|
||||
{0, 0, 0, 0}};
|
||||
{ 0, 0, 0, 0 } };
|
||||
|
||||
/* Set default options. */
|
||||
nwipe_options.autonuke = 0;
|
||||
nwipe_options.autopoweroff = 0;
|
||||
nwipe_options.method = &nwipe_dodshort;
|
||||
nwipe_options.prng = &nwipe_twister;
|
||||
nwipe_options.rounds = 1;
|
||||
nwipe_options.noblank = 0;
|
||||
nwipe_options.nousb = 0;
|
||||
nwipe_options.nowait = 0;
|
||||
nwipe_options.nosignals = 0;
|
||||
nwipe_options.nogui = 0;
|
||||
nwipe_options.sync = 100000;
|
||||
nwipe_options.sync = DEFAULT_SYNC_RATE;
|
||||
nwipe_options.verbose = 0;
|
||||
nwipe_options.verify = NWIPE_VERIFY_LAST;
|
||||
memset( nwipe_options.logfile, '\0', sizeof( nwipe_options.logfile ) );
|
||||
|
||||
@@ -143,12 +155,24 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
break;
|
||||
}
|
||||
|
||||
if( strcmp( nwipe_options_long[i].name, "autopoweroff" ) == 0 )
|
||||
{
|
||||
nwipe_options.autopoweroff = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if( strcmp( nwipe_options_long[i].name, "noblank" ) == 0 )
|
||||
{
|
||||
nwipe_options.noblank = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if( strcmp( nwipe_options_long[i].name, "nousb" ) == 0 )
|
||||
{
|
||||
nwipe_options.nousb = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if( strcmp( nwipe_options_long[i].name, "nowait" ) == 0 )
|
||||
{
|
||||
nwipe_options.nowait = 1;
|
||||
@@ -168,11 +192,17 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
break;
|
||||
}
|
||||
|
||||
if( strcmp( nwipe_options_long[i].name, "verbose" ) == 0 )
|
||||
{
|
||||
nwipe_options.verbose = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if( strcmp( nwipe_options_long[i].name, "sync" ) == 0 )
|
||||
{
|
||||
if( sscanf( optarg, " %i", &nwipe_options.sync ) != 1 || nwipe_options.sync < 1 )
|
||||
if( sscanf( optarg, " %i", &nwipe_options.sync ) != 1 || nwipe_options.sync < 0 )
|
||||
{
|
||||
fprintf( stderr, "Error: The sync argument must be a positive integer.\n" );
|
||||
fprintf( stderr, "Error: The sync argument must be a positive integer or zero.\n" );
|
||||
exit( EINVAL );
|
||||
}
|
||||
break;
|
||||
@@ -343,6 +373,11 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
|
||||
break;
|
||||
|
||||
case 'v': /* verbose */
|
||||
|
||||
nwipe_options.verbose = 1;
|
||||
break;
|
||||
|
||||
case 'V': /* Version option. */
|
||||
|
||||
printf( "%s version %s\n", program_name, version_string );
|
||||
@@ -364,6 +399,9 @@ int nwipe_options_parse( int argc, char** argv )
|
||||
|
||||
void nwipe_options_log( void )
|
||||
{
|
||||
extern nwipe_prng_t nwipe_twister;
|
||||
extern nwipe_prng_t nwipe_isaac;
|
||||
|
||||
/**
|
||||
* Prints a manifest of options to the log.
|
||||
*/
|
||||
@@ -379,6 +417,15 @@ void nwipe_options_log( void )
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " autonuke = %i (off)", nwipe_options.autonuke );
|
||||
}
|
||||
|
||||
if( nwipe_options.autopoweroff )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " autopoweroff = %i (on)", nwipe_options.autopoweroff );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " autopoweroff = %i (off)", nwipe_options.autopoweroff );
|
||||
}
|
||||
|
||||
if( nwipe_options.noblank )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " do not perform a final blank pass" );
|
||||
@@ -400,6 +447,23 @@ void nwipe_options_log( void )
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " banner = %s", banner );
|
||||
|
||||
if( nwipe_options.prng == &nwipe_twister )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " prng = Mersenne Twister" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nwipe_options.prng == &nwipe_isaac )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac" );
|
||||
}
|
||||
else
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " prng = Undefined" );
|
||||
}
|
||||
}
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " method = %s", nwipe_method_label( nwipe_options.method ) );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " rounds = %i", nwipe_options.rounds );
|
||||
nwipe_log( NWIPE_LOG_NOTICE, " sync = %i", nwipe_options.sync );
|
||||
@@ -435,15 +499,23 @@ void display_help()
|
||||
/* Limit line length to a maximum of 80 characters so it looks good in 80x25 terminals i.e shredos */
|
||||
/* ___12345678901234567890123456789012345678901234567890123456789012345678901234567890< Do not exceed */
|
||||
puts( " -V, --version Prints the version number\n" );
|
||||
puts( " -v, --verbose Prints more messages to the log\n" );
|
||||
puts( " -h, --help Prints this help\n" );
|
||||
puts( " --autonuke If no devices have been specified on the command line," );
|
||||
puts( " starts wiping all devices immediately. If devices have" );
|
||||
puts( " been specified, starts wiping only those specified" );
|
||||
puts( " devices immediately.\n" );
|
||||
puts( " --sync=NUM Will perform a sync after NUM writes (default: 0)" );
|
||||
puts( " 0 - fdatasync after the disk is completely written" );
|
||||
puts( " 1 - fdatasync after every write" );
|
||||
puts( " 1000000 - fdatasync after 1000000 writes ect." );
|
||||
puts( " --autopoweroff Power off system on completion of wipe delayed for" );
|
||||
puts( " for one minute. During this one minute delay you can" );
|
||||
puts( " abort the shutdown by typing sudo shutdown -c\n" );
|
||||
printf( " --sync=NUM Will perform a sync after NUM writes (default: %d)\n", DEFAULT_SYNC_RATE );
|
||||
puts( " 0 - fdatasync after the disk is completely written" );
|
||||
puts( " fdatasync errors not detected until completion." );
|
||||
puts( " 0 is not recommended as disk errors may cause" );
|
||||
puts( " nwipe to appear to hang" );
|
||||
puts( " 1 - fdatasync after every write" );
|
||||
puts( " Warning: Lower values will reduce wipe speeds." );
|
||||
puts( " 1000 - fdatasync after 1000 writes etc.\n" );
|
||||
puts( " --verify=TYPE Whether to perform verification of erasure" );
|
||||
puts( " (default: last)" );
|
||||
puts( " off - Do not verify" );
|
||||
@@ -462,15 +534,17 @@ void display_help()
|
||||
puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac)\n" );
|
||||
puts( " -r, --rounds=NUM Number of times to wipe the device using the selected" );
|
||||
puts( " method (default: 1)\n" );
|
||||
puts( " --noblank Do not blank disk after wipe" );
|
||||
puts( " --noblank Do NOT blank disk after wipe" );
|
||||
puts( " (default is to complete a final blank pass)\n" );
|
||||
puts( " --nowait Do not wait for a key before exiting" );
|
||||
puts( " --nowait Do NOT wait for a key before exiting" );
|
||||
puts( " (default is to wait)\n" );
|
||||
puts( " --nosignals Do not allow signals to interrupt a wipe" );
|
||||
puts( " --nosignals Do NOT allow signals to interrupt a wipe" );
|
||||
puts( " (default is to allow)\n" );
|
||||
puts( " --nogui Do not show the GUI interface. Automatically invokes" );
|
||||
puts( " --nogui Do NOT show the GUI interface. Automatically invokes" );
|
||||
puts( " the nowait option. Must be used with the --autonuke" );
|
||||
puts( " option. Send SIGUSR1 to log current stats\n" );
|
||||
puts( " --nousb Do NOT show or wipe any USB devices whether in GUI" );
|
||||
puts( " mode, --nogui or --autonuke modes.\n" );
|
||||
puts( " -e, --exclude=DEVICES Up to ten comma separated devices to be excluded" );
|
||||
puts( " --exclude=/dev/sdc" );
|
||||
puts( " --exclude=/dev/sdc,/dev/sdd" );
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#define NWIPE_KNOB_STAT "/proc/stat"
|
||||
#define MAX_NUMBER_EXCLUDED_DRIVES 10
|
||||
#define MAX_DRIVE_PATH_LENGTH 200 // e.g. /dev/sda is only 8 characters long, so 200 should be plenty.
|
||||
#define DEFAULT_SYNC_RATE 100000
|
||||
|
||||
/* Function prototypes for loading options from the environment and command line. */
|
||||
int nwipe_options_parse( int argc, char** argv );
|
||||
@@ -48,7 +49,9 @@ void display_help();
|
||||
typedef struct
|
||||
{
|
||||
int autonuke; // Do not prompt the user for confirmation when set.
|
||||
int autopoweroff; // Power off on completion of wipe
|
||||
int noblank; // Do not perform a final blanking pass.
|
||||
int nousb; // Do not show or wipe any USB devices.
|
||||
int nowait; // Do not wait for a final key before exiting.
|
||||
int nosignals; // Do not allow signals to interrupt a wipe.
|
||||
int nogui; // Do not show the GUI.
|
||||
@@ -59,6 +62,7 @@ typedef struct
|
||||
nwipe_prng_t* prng; // The pseudo random number generator implementation.
|
||||
int rounds; // The number of times that the wipe method should be called.
|
||||
int sync; // A flag to indicate whether and how often writes should be sync'd.
|
||||
int verbose; // Make log more verbose
|
||||
nwipe_verify_t verify; // A flag to indicate whether writes should be verified.
|
||||
} nwipe_options_t;
|
||||
|
||||
|
||||
28
src/pass.c
28
src/pass.c
@@ -248,6 +248,9 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
|
||||
/* Counter to track when to do a fdatasync. */
|
||||
int i = 0;
|
||||
|
||||
/* general index counter */
|
||||
int idx;
|
||||
|
||||
if( c->prng_seed.s == NULL )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_SANITY, "__FUNCTION__: Null seed pointer." );
|
||||
@@ -260,8 +263,9 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create the output buffer. */
|
||||
b = malloc( c->device_stat.st_blksize );
|
||||
/* Create the initialised output buffer. Initialised because we don't want memory leaks
|
||||
* to disk in the event of some future undetected bug in a prng or it's implementation ) */
|
||||
b = calloc( c->device_stat.st_blksize, sizeof( char ) );
|
||||
|
||||
/* Check the memory allocation. */
|
||||
if( !b )
|
||||
@@ -317,6 +321,26 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
|
||||
/* Fill the output buffer with the random pattern. */
|
||||
c->prng->read( &c->prng_state, b, blocksize );
|
||||
|
||||
/* For the first block only, check the prng actually wrote something to the buffer */
|
||||
if( z == c->device_size )
|
||||
{
|
||||
idx = c->device_stat.st_blksize;
|
||||
while( idx > 0 )
|
||||
{
|
||||
if( b[idx] != 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "prng stream is active" );
|
||||
break;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
if( idx == 0 )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_FATAL, "ERROR, prng wrote nothing to the buffer" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the next block out to the device. */
|
||||
r = write( c->device_fd, b, blocksize );
|
||||
|
||||
|
||||
46
src/prng.c
46
src/prng.c
@@ -9,7 +9,7 @@
|
||||
*
|
||||
* This program 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 General Public License for more
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
@@ -19,14 +19,15 @@
|
||||
|
||||
#include "nwipe.h"
|
||||
#include "prng.h"
|
||||
#include "context.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include "mt19937ar-cok/mt19937ar-cok.h"
|
||||
#include "isaac_rand/isaac_rand.h"
|
||||
|
||||
nwipe_prng_t nwipe_twister = {"Mersenne Twister (mt19937ar-cok)", nwipe_twister_init, nwipe_twister_read};
|
||||
nwipe_prng_t nwipe_twister = { "Mersenne Twister (mt19937ar-cok)", nwipe_twister_init, nwipe_twister_read };
|
||||
|
||||
nwipe_prng_t nwipe_isaac = {"ISAAC (rand.c 20010626)", nwipe_isaac_init, nwipe_isaac_read};
|
||||
nwipe_prng_t nwipe_isaac = { "ISAAC (rand.c 20010626)", nwipe_isaac_init, nwipe_isaac_read };
|
||||
|
||||
int nwipe_u32tobuffer( u8* buffer, u32 rand, int len )
|
||||
{
|
||||
@@ -52,6 +53,8 @@ int nwipe_u32tobuffer( u8* buffer, u32 rand, int len )
|
||||
|
||||
int nwipe_twister_init( NWIPE_PRNG_INIT_SIGNATURE )
|
||||
{
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Initialising Mersenne Twister prng" );
|
||||
|
||||
if( *state == NULL )
|
||||
{
|
||||
/* This is the first time that we have been called. */
|
||||
@@ -90,6 +93,8 @@ int nwipe_isaac_init( NWIPE_PRNG_INIT_SIGNATURE )
|
||||
int count;
|
||||
randctx* isaac_state = *state;
|
||||
|
||||
nwipe_log( NWIPE_LOG_NOTICE, "Initialising Isaac prng" );
|
||||
|
||||
if( *state == NULL )
|
||||
{
|
||||
/* This is the first time that we have been called. */
|
||||
@@ -135,18 +140,31 @@ int nwipe_isaac_init( NWIPE_PRNG_INIT_SIGNATURE )
|
||||
|
||||
int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE )
|
||||
{
|
||||
/* The purpose of this function is unclear, as it does not do anything except immediately return !
|
||||
* Because the variables in the macro NWIPE_PRNG_READ_SIGNATURE were then unused this throws
|
||||
* up a handful of compiler warnings, related to variables being unused. To stop the compiler warnings
|
||||
* I've simply put in a (void) var so that compiler sees the variable are supposed to be unused.
|
||||
*
|
||||
* As this code works, I thought it best not to remove this function, just in case it serves
|
||||
* some purpose or is there for future use.
|
||||
*/
|
||||
u32 i = 0;
|
||||
u32 ii;
|
||||
u32 words = count / SIZE_OF_ISAAC; // the values of isaac is strictly 4 bytes
|
||||
u32 remain = count % SIZE_OF_ISAAC; // the values of isaac is strictly 4 bytes
|
||||
|
||||
(void) state;
|
||||
(void) buffer;
|
||||
(void) count;
|
||||
randctx* isaac_state = *state;
|
||||
|
||||
/* Isaac returns 4-bytes per call, so progress by 4 bytes. */
|
||||
for( ii = 0; ii < words; ++ii )
|
||||
{
|
||||
/* get the next 32bit random number */
|
||||
isaac( isaac_state );
|
||||
|
||||
nwipe_u32tobuffer( (u8*) ( buffer + i ), isaac_state->randrsl[0], SIZE_OF_ISAAC );
|
||||
i = i + SIZE_OF_ISAAC;
|
||||
}
|
||||
|
||||
/* If there is some remainder copy only relevant number of bytes to not overflow the buffer. */
|
||||
if( remain > 0 )
|
||||
{
|
||||
/* get the next 32bit random number */
|
||||
isaac( isaac_state );
|
||||
|
||||
nwipe_u32tobuffer( (u8*) ( buffer + i ), isaac_state->randrsl[0], SIZE_OF_ISAAC );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -54,4 +54,7 @@ int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE );
|
||||
/* Size of the twister is not derived from the architecture, but it is strictly 4 bytes */
|
||||
#define SIZE_OF_TWISTER 4
|
||||
|
||||
/* Size of the isaac is not derived from the architecture, but it is strictly 4 bytes */
|
||||
#define SIZE_OF_ISAAC 4
|
||||
|
||||
#endif /* PRNG_H_ */
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
* used by configure to dynamically assign those values
|
||||
* to documentation files.
|
||||
*/
|
||||
const char* version_string = "0.28";
|
||||
const char* version_string = "0.31";
|
||||
const char* program_name = "nwipe";
|
||||
const char* author_name = "Martijn van Brummelen";
|
||||
const char* email_address = "git@brumit.nl";
|
||||
const char* years = "2020";
|
||||
const char* years = "2021";
|
||||
const char* copyright = "Copyright Darik Horn <dajhorn-dban@vanadac.com>\n\
|
||||
Modifications to original dwipe Copyright Andy Beverley <andy@andybev.com>\n\
|
||||
This is free software; see the source for copying conditions.\n\
|
||||
There is NO warranty; not even for MERCHANTABILITY or FITNESS\n\
|
||||
FOR A PARTICULAR PURPOSE.\n";
|
||||
const char* banner = "nwipe 0.28";
|
||||
const char* banner = "nwipe 0.31";
|
||||
|
||||
Reference in New Issue
Block a user