113 Commits
v0.32 ... v0.33

Author SHA1 Message Date
PartialVolume
1d67d9e0d3 Merge pull request #411 from PartialVolume/Bump_to_0.33
Bump to v0.33
2022-03-20 14:15:05 +00:00
PartialVolume
f63862d042 Bump to v0.33
Updated:
CHANGELOG.md
configure.ac
man/nwipe.1
src/version.c
2022-03-20 14:11:46 +00:00
PartialVolume
65bc03da9a Merge pull request #410 from PartialVolume/fix_segfault_when_logfile_cannot_be_created_due_to_permissions
Fix obscure segfault when --logfile option used with a non writable directory.
2022-03-15 23:07:16 +00:00
PartialVolume
949f2b25e5 Bump version 2022-03-15 23:05:02 +00:00
PartialVolume
62e7876c74 Fix obscure segfault when --logfile option used.
If you use the --logfile option but specify a filename
that will be created in a directory that is not writable,
for instance, a system directory such as /proc/sys/ or
your current directory happens to be a system directory
that you are running nwipe from while not specifying a
writable path for the log file then nwipe would exit with
a segfault.

This is now fixed and if the logfile cannot be created
or opened then an appropriate message is displayed and
nwipe is aborted.
2022-03-15 19:58:13 +00:00
PartialVolume
648cad7645 Merge pull request #409 from PartialVolume/fix_nwipe_not_exiting_when_konsole_exited_before_nwipe_during_wipe
Fix_nwipe_not_exiting_when_using_konsole
2022-03-03 20:06:13 +00:00
PartialVolume
791c6f3975 Fix_nwipe_not_exiting_when_using_konsole
This fixes a issue related to konsole and terminals based on Konsole,
like cool retro terminal. If you exit the terminal before exiting nwipe,
nwipe will then continue running in the background but detached from any
terminals input/output. This causes a call to halfdelay()/getch() to
return immediately, thus removing the delay and causing the thread to
run at full speed causing 100% CPU in a core. This requires nwipe to
then be killed manually. This patch is related to the last patch in
that both patches do much the same thing but the previous patch fixes
the problem when nwipe is sitting at the drive selection screen, while
this patch fixes the problem during a wipe.

This problem would only be seen in specific KDE konsole related
terminals and only if you do not exit nwipe by using nwipe's control c
to abort or use the space bar on completion of the wipe.

Much like the same check we perform in the nwipe_gui_select() function,
here we check that we are not looping any faster than as defined by the
halfdelay() function, typically this loop runs at 10 times a second.
This check makes sure that if the loop runs faster than double this
value i.e 20 times a second then the program exits. This check is
therefore determining whether the getch() function is returning
immediately rather than blocking for the defined period of 100ms.
Why is this necessary? Some terminals (konsole & deriviatives) that are
exited while nwipe is still running fail to terminate nwipe this causes
the halfdelay()/getch() functions to immediately fail causing the loop
frequency to drastically increase. We detect that speed increase here
and therefore close down nwipe. This doesn't affect the use of the tmux
terminal by which you can detach and reattach to running nwipe
processes. The tmux terminal will still work correctly when a nwipe
session is detached.
2022-03-03 19:48:44 +00:00
PartialVolume
3f3ea5e04b Merge pull request #408 from PartialVolume/Fix_100%CPU_when_konsole_closed
Fixes a 100% CPU usage on Konsole based terminal
2022-03-02 19:39:54 +00:00
PartialVolume
175b246291 Fixes a 100% CPU usage on Konsole based terminal
when Konsole terminal exited while nwipe is sitting at the
drive selection screen.

To avoid 100% CPU usage, check for a runaway condition caused by the
function "keystroke = getch() that immediately returns an error
condition. We check for an error condition because getch() returns a
ERR value when the timeout value "timeout( 250 );" expires as well as
when a real error occurs. We can't differentiate from normal operation
and a failure of the getch function to block for the specified period
of timeout. So here we check the while loop hasn't exceeded the number
of expected iterations per second ie. a timeout(250) block value of
250ms means we should not see any more than (1000/250) = 4 iterations.
We double this to 8 to allow a little tolerance. Why is this necessary?
It's been found that in KDE konsole and other terminals based on the QT
terminal engine exiting the terminal without first existing nwipe
results in nwipe remaining running but detached from any interface
which causes getch to fail and its associated timeout. So the CPU or
CPU core rises to 100%. Here we detect that failure and exit nwipe
gracefully with the appropriate error. This does not affect use of
tmux for attaching or detaching from a running nwipe session when
sitting at the selection screen. All other terminals correctly
terminate nwipe when the terminal itself is exited.
2022-03-02 19:34:05 +00:00
PartialVolume
58576f8191 Merge pull request #407 from PartialVolume/Fix_temperature_update_in_drive_selection_window
Fix temperature update in drive selection window
2022-02-25 22:47:06 +00:00
PartialVolume
1384d8a6d7 Fix temperature update in drive selection window
This fixes a problem where the drive temperature is not updated
automatically in the drive selection window only. The temperature
is however updated every correctly every 60 seconds during a wipe in
the wipe status window.

This bug would probably never be noticed by most people as usually the
drive temperature changes slowly and only rises once a wipe has started.

The only time I imagine it would have been noticed would have been if
the drive temperature was already high and you were trying to reduce the
temperature by cooling before starting a wipe.

This has now been corrected so that the temperature in the drive
selection window is updated every 60 seconds.
2022-02-25 22:40:07 +00:00
PartialVolume
7f16dd3f74 Merge pull request #406 from PartialVolume/fix_spurious_message_on_abort_before_wipe_starts_control_c
Fix spurious message on abort before wipe.
2022-02-25 15:47:18 +00:00
PartialVolume
14f70661d8 Fix spurious message on abort before wipe.
This patch fixes a minor display issue that occurs when
a user aborts a wipe before a wipe has started. It only occurs
if the user had selected one or more drives for wipe and then
aborted before starting the wipe. The spurious message only
occurs in a virtual terminal, i.e. /dev/tty1, /dev/tty2, /dev/console
It does not occur in terminal applications such as konsole, xterm,
terminator etc.

The spurious message that appears in the main window, states that
"/dev/sdxyz 100% complete" along with garbage values in the statistics
window. The message appears for a fraction of a second before being
replaced with the textual log information that correctly states that
the user aborted and no wipe was started.

Basically the gui status information update function tries to update
the data when the wipe hasn't even started. The fix is to only update
the statistics information only if a wipe has started by checking the
'global_wipe_status' value which indicates whether any wipe started. '1'
indicates that a wipe has started, else '0' if no wipe has started.
2022-02-25 15:38:42 +00:00
PartialVolume
dcd1d100ca Merge pull request #404 from PartialVolume/master
Bump minor version to 0.32.023
2022-01-13 20:31:11 +00:00
PartialVolume
334bcadae1 Bump minor version 2022-01-13 20:20:58 +00:00
PartialVolume
dff450c49d Merge pull request #403 from martijnvanbrummelen/revert-402-revert-401-update_isaac64_command_line_options_help_and_man_page
Revert "Revert "Isaac64, update options, help and man page""
2022-01-13 20:05:43 +00:00
PartialVolume
40569ce1c0 Revert "Revert "Isaac64, update options, help and man page"" 2022-01-13 20:03:47 +00:00
PartialVolume
34fca0747a Merge pull request #402 from martijnvanbrummelen/revert-401-update_isaac64_command_line_options_help_and_man_page
Revert "Isaac64, update options, help and man page" Checks failed.
2022-01-13 19:32:36 +00:00
PartialVolume
110f62de00 Revert "Isaac64, update options, help and man page" 2022-01-13 19:30:10 +00:00
PartialVolume
1705b31ae8 Merge pull request #401 from PartialVolume/update_isaac64_command_line_options_help_and_man_page
Isaac64, update options, help and man page
2022-01-13 19:27:52 +00:00
PartialVolume
1e43f17650 Isaac64, update options, help and man page 2022-01-13 19:25:43 +00:00
PartialVolume
8313506ec5 Merge pull request #400 from PartialVolume/Fix_summary_table_on_specific_failure
Fix obscure incorrect summary table status
2022-01-12 21:14:22 +00:00
PartialVolume
978c4e9c8b Fix obscure incorrect summary table status
If the drive becomes non responsive during the wipe, the MB/s will
slowly drop towards 0MB/s and will display a FAILURE -1 error. The logs
will display errors and nwipe's return status will be non zero, however
the summary table may display erased rather than FAILURE, this is because
the wipe thread exited prematurely without setting the pass error.

This fixes the error by checking the context's result status, i.e non zero
on failure and if pass equals zero it makes pass equal to one. This is
then picked up by the summary table log code which then marks the status
correctly as FAILURE in the summary table.
2022-01-12 21:03:58 +00:00
PartialVolume
5ca7458b8c Bump version to 0.32.021 2022-01-09 15:18:32 +00:00
PartialVolume
0bc79f9feb Merge pull request #399 from chkboom/gutmann
Random passes in the Gutmann method should not be rearranged.
2022-01-09 15:16:05 +00:00
AK-47
0b959b62da Random passes in the Gutmann method should not be rearranged.
https://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html
"... random passes before and after the erase process, and by performing the deterministic passes in random order ..."
"The deterministic patterns between the random writes are permuted before the write is performed, ..."
2022-01-08 12:50:18 +11:00
PartialVolume
5e9ff6dfa5 Bumped version and year. 2022-01-06 23:37:02 +00:00
PartialVolume
d964c9245d Merge pull request #398 from chkboom/isaac64
Added ISAAC-64 PRNG for 64-bit systems.
2022-01-06 23:32:56 +00:00
AK-47
aa2c7727c4 Removed asserts and make "remain" const.
Attempt to fix formatting.
2022-01-07 00:28:39 +11:00
AK-47
3094fc2fa7 Leave the blanking setting alone when changing the verification setting. 2022-01-06 21:42:01 +11:00
AK-47
85fbba947a Select ISAAC-64 by default on a >=64-bit CPU.
Otherwise choose ISAAC instead of Mersenne Twister.
2022-01-06 20:57:18 +11:00
AK-47
6dff23d6b2 Significantly improved ISAAC and ISAAC-64 performance.
Each ISAAC call generates a block of integers, but only the first integer was used before the PRNG was called again.
This resulted in most of the random numbers being wasted and more calls to the PRNG than was necessary.
Also fixed some segmentation faults in ISAAC-64 code.
2022-01-06 13:55:00 +11:00
AK-47
76ca47f2cb Added ISAAC-64 PRNG for 64-bit systems.
Use RANDIZL=8 as recommended by ISAAC author.
Fixed possible buffer overflow in nwipe_isaac_read().
Slight performance improvement.
2022-01-06 01:36:12 +11:00
PartialVolume
fe9666bd41 Merge pull request #395 from Firminator/patch-2
Update README.md
2021-12-13 09:12:04 +00:00
Firminator
a19e07bd1b Update README.md
* remove redundant paragraphs and information especially regarding ShredOS
* move certain paragraphs around to streamline the readme and for better readability
* update links
* some minor changes
2021-12-13 00:33:30 -05:00
PartialVolume
c4430f149c Merge pull request #394 from PartialVolume/Mitigate_against_smartctls_inconsistent_use_of_case_in_labelling
Fix missing serial number on SAS drive. Fixes #384
2021-12-12 20:28:08 +00:00
PartialVolume
a83a27f8e5 Fix missing serial number on SAS drive
This was caused by inconsistent labeling of the
serial number by smartctl. In a majority of cases
smartctl would output serial number data using
the label "Serial Number:" however on a SAS
drive we found that smartctl output the label
as "Serial number:" i.e. differs with a lower
case 'n'. Unfortunately we were doing a case
sensitive search for "Serial Number" so the result
being the serial number was not found.

This patch converts both strings in the search
to lower case before searching.

In addition a new field was added to the
anonymize list, "logical unit id:" so when the
-q option is used "serial number", "lu wwn device id:"
and "logical unit id:" are all now anonymized in the
smartctl debug data.
2021-12-12 20:22:35 +00:00
PartialVolume
254a0efd2c Merge pull request #393 from PartialVolume/Improve_GUI_thread_cancellation_eror_handling
Improve GUI thread cancellation messaging
2021-12-08 23:47:38 +00:00
PartialVolume
323fc38631 Improve GUI thread cancellation messaging
If pthread_join failed, nwipe would report an error
but would also report that the thread had been
cancelled. This has been corrected so that only
the error message is displayed in a fault condition.
2021-12-08 23:43:01 +00:00
PartialVolume
7f547e7ccb Merge pull request #392 from PartialVolume/Improve_thread_cancellation_error_reporting
Improve thread cancellation error reporting
2021-12-07 23:17:25 +00:00
PartialVolume
c433326c9f Improve thread cancellation error reporting
Check for specific errors.
Add retry loop with timeout for pthread_join.
2021-12-07 23:10:20 +00:00
PartialVolume
4351b3db5d Merge pull request #391 from PartialVolume/Fix_use_of_modprobe_on_Debian_11_part2
Would help if I explicitly stated the paths ;-)
2021-12-02 22:51:48 +00:00
PartialVolume
5eb43855c7 Would help if I explicitly stated the paths :'-) 2021-12-02 22:47:48 +00:00
PartialVolume
86174b227d Merge pull request #390 from PartialVolume/Fix_use_of_modprobe_on_Debian_11
Check multiple paths for modprobe
Fixes #389
2021-12-02 22:34:09 +00:00
PartialVolume
acba2c8065 Check multiple paths for modprobe
Particularly relevant to Debian which when logged in as root
doesn't put /sbin in the $PATH environment setting.

This might have caused temperatures to not be available on Debian
systems, but not necessarily on distros based on Debian like
Ubuntu which would have worked ok.
2021-12-02 22:30:39 +00:00
PartialVolume
0d3e1af83d Merge pull request #388 from PartialVolume/Fix_second_occurence_of_incorrect_specifier
Fix 2nd occurrence of incorrect format specifier.
2021-12-01 19:45:20 +00:00
PartialVolume
981f666150 Fix 2nd occurrence of incorrect format specifier.
Causing incorrect sect/block/device size to be
printed in nwipe_log but only for 32 bit builds.
2021-12-01 19:42:28 +00:00
PartialVolume
4f531e65db Merge pull request #387 from PartialVolume/Fix_nwipe_log_format_specifier_incorrect
Fix nwipe log format specifier incorrect
2021-12-01 19:33:16 +00:00
PartialVolume
181ef543de nwipe_log format specifier doesn't match variable.
The format specifier didn't match the size of the variable that holds
c2[i]->device_sector_size which is an int. This didn't appear to cause
a problem with reporting in a 64 bit build. It does cause a problem in
a 32 bit build displaying a very large & incorrect number for sector,
block and device sizes.

This doesn't cause any issues with the overall function, simply
incorrect sector, block and device sizes in 32 bit builds as displayed
in the nwipe log.

I also changed the signed long long for c2[i]->device _size to a
unsigned long long as there is little point in a negative device size.
2021-12-01 19:20:34 +00:00
PartialVolume
aab863ea7d Update ShredOS link 2021-12-01 05:50:34 +00:00
PartialVolume
ef06fed886 Merge pull request #383 from Firminator/patch-1
Update options.c with additional infor for -q
2021-11-18 15:34:05 +00:00
Firminator
6396825eb6 Update options.c
* added additional info for -q, i.e. what data is being removed from GUI and logs
* removed superfluous new line break
2021-11-18 10:11:03 -05:00
PartialVolume
b35b14ba42 Merge pull request #382 from PartialVolume/Remove_trailing_character
Remove ')' character in nwipe_log message
2021-11-18 12:07:29 +00:00
PartialVolume
2b63fb74cb Remove ')' character in nwipe_log message 2021-11-18 12:02:35 +00:00
PartialVolume
fd11b9df35 Merge pull request #381 from PartialVolume/Update_hwmon_search_directories
Update temperature for some nvme devices
2021-11-18 11:29:27 +00:00
PartialVolume
0677cebe5b Update temperature
Add /sys/class/hwmon/hwmonX/device/ to the list
of directories to search for a given device.

Some nvme devices/controllers put the device name
in /sys/class/hwmon/hwmonX/device/ rather than
/sys/class/hwmon/hwmonX/device/nvme/nvme0/

Update debug messaging.
2021-11-18 11:25:44 +00:00
PartialVolume
6b930863a6 Update comment 2021-11-17 20:32:15 +00:00
PartialVolume
e07ae7e0ef Merge pull request #380 from PartialVolume/Update_NVME_temperature_code
Update nvme temperatures.
2021-11-17 19:30:39 +00:00
PartialVolume
1744d89692 Update nvme temperatures.
For sdX devices we look in
/sys/class/hwmon/hwmonX/block for the device
name.

However, for nvme we access the device name
by looking in ..
/sys/class/hwmon/hwmonX/device/nvme/nvme0

nvme0n1

Multiple nvme drives/controllers will need
to be tested.
2021-11-17 19:27:27 +00:00
PartialVolume
8b36b3d204 Merge pull request #379 from PartialVolume/Add_anonymized_label_to_banner
Make it clear we are in anonymized mode
2021-11-17 16:26:06 +00:00
PartialVolume
c0466c4850 Make it clear we are in anonymized mode
When selecting -q or --quiet as an nwipe
option, append " (ANONYMIZED)" to the nwipe
banner.
2021-11-17 16:14:28 +00:00
PartialVolume
bb7199adf6 Bump version to v0.32.010 2021-11-17 15:39:54 +00:00
PartialVolume
e2cd608741 Merge pull request #378 from PartialVolume/Add_VRFY_instead_of_WIPE_when_verify_ones_or_zeros_only_is_selected
Distinguish between a wipe & verify
2021-11-17 15:38:16 +00:00
PartialVolume
a4d2418597 Distinguish between a wipe & verify
In the drive selection window when you
select a drive, the drive is identified
as selected for wiping with the [wipe]
label, however if you then select a
verify only method such as 'verify with
ones' or 'verify with zeros' it still
says [wipe] which is technically a
contradiction.

This patch changes the [wipe] to a
[vrfy] when a verify only method is
selected. If a method is selected
that writes data to the disc then the
label is displayed as [wipe].
2021-11-17 15:27:45 +00:00
PartialVolume
40ae117db4 Merge pull request #377 from PartialVolume/add_temperature_support_to_nvme_drives
Add temperature support to NVME drives, patch #1 ready for checking @Firminator . Thanks
2021-11-17 14:44:53 +00:00
PartialVolume
4ef3dbc5dd Add temperature support to NVME drives
Patch #1 (first check)
2021-11-17 14:37:16 +00:00
PartialVolume
93fe596c04 Merge pull request #375 from PartialVolume/Dont_calculate_ETA_when_throughput_is_zero
Fixes ETA under fault condition
2021-11-17 11:53:38 +00:00
PartialVolume
dd44cc8176 Fixes ETA under fault condition
If a faulty drive fails mid wipe and it's
throughput drops until eventually reaching
zero. The ETA calculation grows to an enormously
high value.

This patch prevents the ETA being calculated if
the throughput for a given drive drops below
100,000 bytes per second. In this way we can still
see that something is wrong because the ETA is much
higher than normal but prevents the sort of calculation
that looks like this ! 90867213:29:12 i.e ..
90,867,213 hours, 29 minutes and 12 seconds, or put
another way, 3,786,133 days or 10,372 years.
2021-11-17 11:50:22 +00:00
PartialVolume
c6fda62558 Merge pull request #374 from PartialVolume/Make_verify_error_message_more_succinct_to_reduce_line_wrap_on_many_verification_errors
Make verify & pass error succinct
2021-11-17 10:45:10 +00:00
PartialVolume
87f63e1388 Make verify & pass error succinct
When many verification or pass errors are detected
the status line can wrap on a 80 column display.

This patch makes the error message more succinct
which will free up about 10 characters & prevents
the line wrapping.
2021-11-17 10:40:36 +00:00
PartialVolume
bfe5939e33 Merge pull request #373 from PartialVolume/Fix_intermittent_FAILED_message_instead_of_UABORTED_on_control-C
Fix summary table - Control-C
2021-11-17 10:03:45 +00:00
PartialVolume
fb6b47d12a Fix summary table - Control-C
If you used control-c during a wipe,
the summary table would report FAILED
rather than UABORTED, even though no
errors had occured and no errors were
reported in the error summary table.

The correct message on control-c abort
should be UABORTED if no errors on that
drive had so far been detected or FAILED
if errors had been detected.

nwipe reported correctly when letting
the wipe continue to it's natural completion.

This patch fixes that issue.
2021-11-17 09:59:20 +00:00
PartialVolume
5d0d0ecb8a Merge pull request #371 from PartialVolume/Add_LU_WWN_ID_to_the_list_of_items_that_can_be_anonymized
Anonymize 'LU WWN ID' when -q specified.
2021-11-16 17:54:11 +00:00
PartialVolume
5cb27e60ce Anonymize 'LU WWN ID' when -q specified.
Add 'LU WWN ID' to the list of data returned
by smartctl that should be anonymized when
-q or --quiet is specified.
2021-11-16 17:48:50 +00:00
PartialVolume
f3f5ab1cac Bump version 2021-11-15 22:00:57 +00:00
PartialVolume
357031ce54 Merge pull request #367 from PartialVolume/Anonymize_SMBIOS-DMI_data_in_log_when_q_option_used
Anonymize SMBIOS/DMI data if -q --quiet specified
2021-11-15 21:57:41 +00:00
PartialVolume
190dae3dec Anonymize SMBIOS/DMI data if -q --quiet specified 2021-11-15 21:46:20 +00:00
PartialVolume
b9cb2369d1 Merge pull request #366 from PartialVolume/Add_anonymize_serial_numbers_option
Add -q --quiet option - anonymize serial numbers
2021-11-15 18:41:03 +00:00
PartialVolume
e982ca5fee Add -q --quiet option - anonymize serial numbers
Anonymize the serial numbers in the gui, the
log and the summary table.

If a serial number was obtained from the device,
it is replaced with "XXXXXXXXXXXXXXX".

If the serial number could not be obtained from the
device, it's replaced with "???????????????".
2021-11-15 18:19:47 +00:00
PartialVolume
a074be7f87 Merge pull request #365 from PartialVolume/Remove_dev_prefix_for_long_device_names_for_gui
Remove /dev/ from gui for long filenames
2021-11-15 10:07:47 +00:00
PartialVolume
0960fd1259 Remove /dev/ from gui for long filenames
This fixes column alignment issues in the gui
with nvme drives i.e. nvme0n1 etc. If the drive
name including path exceeds 8 characters the
/dev/ is removed and prefixed with spaces to
a total max length of 8 characters.
2021-11-15 09:57:46 +00:00
PartialVolume
4aee9a2d28 Merge pull request #364 from PartialVolume/move_temperature
Moved the temperature readout
2021-11-13 22:06:41 +00:00
PartialVolume
8650b4838a Moved the temperature readout
In both selection and wipe status windows I
moved the temperature readout to the right
of the disk size column.

Also in the wipe status window, by moving to
the right of the disk size column the
temperature is no longer on the same line as
the disk pass progress. This reduces the line
length as I found that in tests if you had
many verification errors the temperature
being on the end of the line would disappear
of the right of the screen.
2021-11-13 21:55:48 +00:00
PartialVolume
07eac4d861 Merge pull request #363 from Firminator/patch-1
Update README.md
2021-11-13 17:07:10 +00:00
Firminator
20ea1bf251 Update README.md
rewording.
2021-11-13 11:25:08 -05:00
Firminator
673310ce6d Update README.md
added netboot.xyz
2021-11-13 11:21:08 -05:00
PartialVolume
a0e63c659b Merge pull request #361 from PartialVolume/temperature_on_select_screen
Added temperature to drive selection window
2021-11-12 23:39:55 +00:00
PartialVolume
90ed59fe06 Added temperature to drive selection window
Also removed 1. 2. etc from drive selection
to reduce the line length. Also removed the
space between > and [, ie "> [wipe]" becomes
">[wipe]" These changes remove 3 characters
and help to reduce the affect of the additional
temperature field [30C] which add 5 characters.
Therefore the line length overall, increased by
5-3 = 2 characters.

This helps to reduce line wrapping on 80
character terminals, when the drive model length
exceeds 24 characters.
2021-11-12 23:23:57 +00:00
PartialVolume
c38c9577bb Bump version 2021-11-10 23:32:38 +00:00
PartialVolume
584f70e3b0 Merge pull request #360 from PartialVolume/Add_drive_temperature
Add drive temperature monitoring
2021-11-10 23:28:04 +00:00
PartialVolume
588784a06b More additions to temperature feature
1. Changed a few nwipe log messages to improve
readability.

2. Added code so that the temperature changes from
- white text = (Temperature within spec)
- red text = max continuous temp reached
- red flashing text = critical upper temperature reached
- black text = minimum continuous temperature reached
- black flashing text = critical lower temperature reached.
2021-11-10 23:16:17 +00:00
PartialVolume
796d5e2294 More changes related to temperature feature
1. Changed gui format specifier to match signed
integer that we changed to in the previous commit.

2. Changed the format specifier in verbose nwipe logging of
the temperatures and moved the nwipe log message that prints
the hwmonX path to the log in order to remove
unnecessary printing to the log.
2021-11-10 19:09:12 +00:00
PartialVolume
e7237a7a75 Changes related to temperature feature
1. Changed u64 to int to support negative
temperature values, i.e. temp1_lcrit may
be as low as -40C

2. In gui surround temperature reading with
square brackets instead of round brackets to
be consistent with the rest of the drive status line
2021-11-10 18:40:42 +00:00
PartialVolume
1d5f2a7899 Stage 2 temperature monitor feature.
Stage 2 modifies the GUI to trigger a temperature
update every 60 seconds. Changes were made to the
drive progress line to include [ 30C ]. The drive
context structure had another variable added that
records the time of the temperature update.

Note. When the temperature data cannot be retrieved
from the hwmon (drivetemp) module the GUI displays
[ --C ]. USB devices, even those adapters that support
ATA pass through, don't seem to work with hwmon (drivetemp),
at least the adapters I have don't work with drivetemp
to monitor temperature.
2021-11-10 12:27:20 +00:00
PartialVolume
397f6fceb3 Stage 1 temperature monitor feature.
Stage 1 adds the additional variables to the drive
context and creates the temperature initialisation
function, which associates a hwmonX directory with
a block device. Also wrote the context update function,
that reads hwmon for each drive context and writes the
temperatures back to the context.

Stage 2 commit to follow which will make changes within
the GUI to call the update function every 60 seconds
and display the temperature information.
2021-11-10 01:27:52 +00:00
PartialVolume
74fa192efa Change message for unknown serial no.
Changed message from (No ATA pass-thru) to (S/N: unknown)
2021-11-07 00:10:38 +00:00
PartialVolume
aa196b9602 Merge pull request #356 from Firminator/patch-2
Update device.c
2021-11-07 00:05:19 +00:00
PartialVolume
4d59c31b8f Bump version to 0.32.002 2021-11-06 00:44:12 +00:00
PartialVolume
056b4745ba Merge pull request #358 from PartialVolume/add_SATA_to_smartctl
Check smartctl for unresolved bus types SATA
2021-11-05 23:47:53 +00:00
PartialVolume
366249b76a Check smartctl for unresolved bus types SATA
For some controllers/drivers the readlink method of
obtaining the bus type for GUI display does not work.

If we haven't already resolved the bus type, we then
also check smartctl for the transport protocol
for SATA.
2021-11-05 23:43:43 +00:00
Firminator
02c1fa4780 Update device.c
correct a few typos not found by codespell
2021-11-04 23:35:00 -04:00
PartialVolume
39de02db8c Merge pull request #353 from DimitriPapadopoulos/codespell_rc
Add a .codespellrc file to run codespell
2021-11-02 19:12:50 +00:00
PartialVolume
e4b033e566 Merge pull request #354 from DimitriPapadopoulos/typo
Typo not found by codespell
2021-11-02 11:28:54 +00:00
Dimitri Papadopoulos
4903f246c0 Typo not found by codespell
The it's → its typo is not detected bsy codespell. Both are valid.
A higher level analysis would be required to detect that kind of typo.
2021-11-02 12:20:59 +01:00
Dimitri Papadopoulos
009ccf294b Add a .codespellrc file to run codespell 2021-11-02 12:10:22 +01:00
PartialVolume
17609ecdcd Merge pull request #352 from DimitriPapadopoulos/spaces
Remove trailing spaces or empty lines
2021-11-02 09:34:37 +00:00
PartialVolume
9f58de6006 Merge pull request #351 from DimitriPapadopoulos/codespell
Typos found by codespell
2021-11-02 09:30:23 +00:00
Dimitri Papadopoulos
c545aa8447 Remove trailing spaces or empty lines 2021-11-02 08:21:34 +01:00
Dimitri Papadopoulos
b2c22d58cb Typos found by codespell 2021-11-02 08:13:48 +01:00
PartialVolume
2459b0a397 Merge pull request #350 from PartialVolume/Add_SAS_to_bus_type_for_GUI
Add SAS to GUI.
2021-11-01 23:02:34 +00:00
PartialVolume
3c4e51a1ff Add SAS to GUI.
For some controllers/drivers the readlink method of
obtaining the bus type for GUI display does not work.

If we haven't already resolved the bus type, we then
also check smartctl for the transport protocol
for SAS.
2021-11-01 22:54:55 +00:00
PartialVolume
0ee4099c64 Merge pull request #348 from PartialVolume/Fix_spaces_overwriting_first_two_chars_of_DOD
Fix slight screen corruption on 80 column display
2021-10-31 21:49:19 +00:00
PartialVolume
089c188b06 Fix slight screen corruption on 80 column display
When highlighting the verify ones option the first two
digits of DoD 5220 .20-M disappear. This patch fixes that
issue.
2021-10-31 21:30:20 +00:00
29 changed files with 1597 additions and 356 deletions

View File

@@ -77,4 +77,3 @@ Standard: Cpp11
TabWidth: 4
UseTab: Never
...

2
.codespellrc Normal file
View File

@@ -0,0 +1,2 @@
[codespell]
skip = ./.git

View File

@@ -1,6 +1,38 @@
RELEASE NOTES
=============
v0.33
-----------------------
- Fixes a slight screen corruption on 80 column display. When highlighting the verify ones option the first two digits of DoD 5220.20-M disappear. This patch fixes that issue.@PartialVolume #348
- For some controllers/drivers the readlink method of obtaining the bus type for GUI display does not work. If we haven't already resolved the bus type, we then also check smartctl for the transport protocol for SAS. @PartialVolume #350
- Check smartctl for unresolved bus types SATA @PartialVolume #358
- Changed message from (No ATA pass-thru) to (S/N: unknown) as the reason the serial number is unknown is because there is no ATA pass through for the chipset being used by the USB to SATA adapter, basically we are making the message more meaningful for the end user rather than for the engineer/programmer that may understand the previous terminology used. @PartialVolume @Firminator #356
- Add drive temperature monitoring and display temperature in degrees Celsius in the GUI. Requires the kernel drivetemp module and makes use of the hwmon sub system in the kernel to extract drive temperatures. Nwipe will automatically load the drivetemp module if it's available. @PartialVolume #360 #361 #364
- Remove /dev/ from gui for long device names. This fixes column alignment issues in the gui with nvme drives i.e. nvme0n1 etc. If the drive name including path exceeds 8 characters the /dev/ is removed and prefixed with spaces to a total max length of 8 characters. @PartialVolume #365
- Add -q --quiet option - anonymize serial numbers and SMBIOS-DMI data. This anonymizes serial numbers and related identifiable information for drives and hardware but does not remove model information in both the GUI and the log displayed by stdout at the end of a wipe and also in the log file if enabled in options. This feature is useful for uploading logs when submitting bug reports. @PartialVolume #366 #367 #371 #379 #383
- Fixes a intermittent FAILED message that is displayed in the summary table when the message should have been UABORTED. The incorrect FAILED message only occurred when using control-C to abort a wipe. @PartialVolume #373
- When many verification or pass errors are detected the status line can wrap on a 80 column display. This patch makes the error message more succinct which will free up about 10 characters & prevents the line wrapping. @PartialVolume #374
- Fixes a problem that occurs with a unresponsive drive that causes the ETA to grow to an enormous value. We now do not calculate an individual drives ETA when the throughput of the drive is zero so avoiding the overall ETA being incorrect for drives that are working correctly when multiple drives are being simultaneously wiped. While a individual drives ETA is calculated it is not displayed but only used to determine the overall ETA when all drives have completed. @PartialVolume #375
- Add temperature monitoring and display with NVMe drives. @PartialVolume #377 #380 #381
- When one of the two verify only methods are selected change the drive selected text from WIPE to VRFY to indicate the drive is not being wiped, but is only being verified. @PartialVolume #378
- Fixes a incorrect sector, block and device sizes in 32 bit builds only as displayed in the nwipe log. This problem had no affect on the wipe as the issue was caused by a incorrect format specifier that affected the log text only. @PartialVolume #387 #388
- Fixes a issue where temperatures may not have been available on Debian systems due to the location of modprobe. Particularly relevant to Debian which when logged in as root doesn't put /sbin in the $PATH environment setting. This issue was not necessarily relevant for Linux distros based on Debian, for instance, Ubuntu where nwipe would have found the modprobe command. @PartialVolume #390 #391
- Improve wipe thread cancellation error checking. @PartialVolume #392
- Improve GUI thread messaging if a pthread_join fails. @PartialVolume #393
- Fixed a missing serial number on SAS drive.@PartialVolume #394
- Added ISAAC-64 for 64 bit systems. Thanks @chkboom #398 #401
- Fixes a problem with the Gutmann wipe where the random passes at the beginning and end were being re-arranged when only the inner passes should be rearranged. Thanks @chkboom #399
- Fixes a obscure incorrect summary table status, while the log text correctly reports the failure. If the drive becomes non responsive during the wipe, the MB/s throughput will slowly drop towards 0MB/s and will display a FAILURE -1 error. The logs will correctly display errors and nwipe's return status will be non zero, however the summary table may display erased rather than FAILURE, this is because
the wipe thread exited prematurely without setting the pass error. This fixes the error by checking the context's result status, i.e non zero on failure and if pass equals zero it makes pass equal to one. This is then picked up by the summary table log code which then marks the status
correctly as FAILURE in the summary table. @PartialVolume #400
- Fixes a spurious message on abort before wipe.This patch fixes a minor display issue that occurs when a user aborts a wipe before a wipe has started. It only occurs if the user had selected one or more drives for wipe and then aborted before starting the wipe. The spurious message only occurs in a virtual terminal, i.e. /dev/tty1, /dev/tty2, /dev/console It does not occur in terminal applications such as konsole, xterm, terminator etc. The spurious message that appears in the main window, states that "/dev/sdxyz 100% complete" along with garbage values in the statistics window. The message appears for a fraction of a second before being replaced with the textual log information that correctly states that the user aborted and no wipe was started. Basically the gui status information update function tries to update the data when the wipe hasn't even started. The fix is to only update the statistics information only if a wipe has started by checking the 'global_wipe_status' value which indicates whether any wipe started. '1' indicates that a wipe has started, else '0' if no wipe has started. @PartialVolume #406
- Fixes temperature update in drive selection window. This fixes a problem where the drive temperature is not updated
automatically in only the drive selection window. The temperature is however updated correctly every 60 seconds during a wipe in the wipe status window. This bug would probably never be noticed by most people as usually the drive temperature changes slowly and only rises once a wipe has started. The only time I imagine it would have been noticed would have been if the drive temperature was already high and you were trying to reduce the temperature by cooling before starting a wipe. This has now been corrected so that the temperature in the drive
selection window is updated every 60 seconds. @PartialVolume #407
- Fixes a zombie nwipe process running at 100% CPU on one core but only on a Konsole based terminal. This only occurred when the Konsole terminal is exited while nwipe is sitting at the drive selection screen but nwipe did not exit when the konsole terminal was closed. If nwipe is exited normally on completion of a wipe or aborted by using control C then this problem would not be seen. Also occurs during a wipe if the konsole terminal is closed without exiting nwipe first, again only on Konsole based terminals. @PartialVolume #408 #409
- Fixes a obscure segfault when --logfile option used with a non writable directory. @PartialVolume #410
v0.32
-----------------------
- Add ones (0xFF) wipe to the methods. Renamed Zero Fill to Fill with Zeros and the new ones wipe, is called Fill with Ones.
@@ -8,7 +40,7 @@ v0.32
- Move method information from below the list of methods to the right of the method list. This allows better use of the screen space by allowing more methods to be added to the list, especially relevant to nwipe running as a standalone application on small distros such as shredos 2020 in frame buffer mode.
- Removed the old DBAN syslinux.cfg configuration hints as not relevant to nwipe. See nwipe --help or man nwipe for command line options.
- Add fdatasync errors to the error summary table.
- During a wipe, you can now toggle between dark screen, blank screen and default blue screen by repeatedly pressing the b key. Dark screen, which is grey text on black background has been introduced to prevent TFT/LCD image persistence on monitors that are sensitive to that issue.
- During a wipe, you can now toggle between dark screen, blank screen and default blue screen by repeatedly pressing the b key. Dark screen, which is grey text on black background has been introduced to prevent TFT/LCD image persistence on monitors that are sensitive to that issue.
v0.31
-----------------------

View File

@@ -3,9 +3,13 @@
![GitHub CI badge](https://github.com/martijnvanbrummelen/nwipe/workflows/ci_ubuntu_16.04/badge.svg)
[![GitHub release](https://img.shields.io/github/release/martijnvanbrummelen/nwipe)](https://github.com/martijnvanbrummelen/nwipe/releases/)
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.
nwipe is a fork of the dwipe command originally used by Darik's Boot and Nuke (DBAN). 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.
nwipe is a program that will securely erase the entire contents of disks. It can wipe a single drive or multiple disks simultaneously. It can operate as both a command line tool without a GUI or with a ncurses GUI as shown in the example below:
![Example wipe](/images/example_wipe.gif)
<i>GIF showing six drives being simultaneously erased. It skips to the completion of all six wipes and shows five drives that were successfully erased and one drive that failed due to an 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.</i>
The user can select from a variety of recognised secure erase methods which include:
@@ -20,31 +24,27 @@ The user can select from a variety of recognised secure erase methods which incl
* Verify Ones - This method only reads the device and checks that it is filled with ones (0xFF).
* HMG IS5 enhanced - Secure Sanitisation of Protectively Marked Information or Sensitive Information
It also includes the following pseudo random number generators:
nwipe also includes the following pseudo random number generators:
* Mersenne Twister
* 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), [SystemRescueCD](https://www.system-rescue.org), [gparted live](https://sourceforge.net/projects/gparted/files/gparted-live-testing/1.2.0-2/) and
[ShredOS 2020](https://github.com/PartialVolume/shredos.2020.02) ShredOS 2020 was developed in particular to showcase nwipe as a fast to boot standalone method similar to DBAN Available in the following architectures x86_64 and i686 (32 bit), with the following formats .iso for CD-R/DVD-R and .img for USB flash drive version and in both legacy bios and UEFI boot. If you want a bootable version of the very latest nwipe master that you can write to a USB flash memory or CD/DVD, 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)
These can be used to overwrite a drive with a stream of randomly generated characters.
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.
nwipe can be found in many [Linux distro repositories](#which-linux-distro-uses-the-latest-nwipe).
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.
![Example wipe](/images/example_wipe.gif)
nwipe is also included in [ShredOS](https://github.com/PartialVolume/shredos.x86_64) which was developed in particular to showcase nwipe as a fast-to-boot standalone method similar to DBAN. ShredOS always contains the latest nwipe version.
## Compiling & Installing
For a development setup, see the [Hacking section](#hacking) below. For a bootable version of the very latest nwipe master that you can write to an USB flash drive or CD/DVD, see the [Quick and easy bootable version of nwipe master section](#quick--easy-usb-bootable-version-of-nwipe-master-for-x86_64-systems) below.
`nwipe` requires the following libraries to be installed:
* ncurses
* pthreads
* parted
and optionally, but recommended!, the following programs:
and optionally, but recommended, the following programs:
* dmidecode
* readlink
@@ -85,19 +85,16 @@ Note. The following programs are optionally installed although recommended. 1. d
#### 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)
#### 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)
If you want a quick and easy way to keep your copy of nwipe running the latest master release of nwipe see the [automating the download and compilation](#automating-the-download-and-compilation-process-for-debian-based-distros) section.
### Compilation
For a development setup, see [the hacking section below](#Hacking).
First create all the autoconf files:
```
./autogen.sh
@@ -133,10 +130,7 @@ make
make install
```
The `-O0 -g` flags disable optimisations. This is required if you're debugging with
`gdb` in an IDE such as Kdevelop. With these optimisations enabled you won't be
able to see the values of many variables in nwipe, not to mention the IDE won't step
through the code properly.
The `-O0 -g` flags disable optimisations. This is required if you're debugging with `gdb` in an IDE such as Kdevelop. With these optimisations enabled you won't be able to see the values of many variables in nwipe, not to mention the IDE won't step through the code properly.
The `-Wall` and `-Wextra` flags enable all compiler warnings. Please submit code with zero warnings.
@@ -146,19 +140,18 @@ make format
```
You will need `clang-format` installed to use the `format` command.
Once done with your coding then the released/patch/fixed code can be compiled,
with all the normal optimisations, using:
Once done with your coding then the released/patch/fixed code can be compiled, 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`
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.
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 libraries are up to 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 only takes 11 seconds to compile 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:
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
@@ -167,7 +160,7 @@ cd ~/nwipe_master/nwipe/src
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](
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
@@ -185,15 +178,17 @@ 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?
## 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 [ShredOS](https://github.com/PartialVolume/shredos.x86_64). The ShredOS image is around 60MB and can be written to an USB flash drive in seconds, allowing you to boot straight into the latest version of nwipe. ShredOS is available for x86_64 (64-bit) and i686 (32-bit) CPU architectures and will boot both legacy BIOS and UEFI devices. It comes as .IMG (bootable USB flash drive image) or .ISO (for CD-R/DVD-R). Instructions and download can be found [here](https://github.com/PartialVolume/shredos.x86_64#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)
And in addition checkout the following distros that all include nwipe:
- [ShredOS 2020](https://github.com/PartialVolume/shredos.2020.02) Always has the latest nwipe release.
- [ShredOS](https://github.com/PartialVolume/shredos.x86_64) Always has the latest nwipe release.
- [netboot.xyz](https://github.com/netbootxyz/netboot.xyz) Can network-boot ShredOS.
- [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/)

View File

@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.64])
AC_INIT([nwipe], [0.32], [git@brumit.nl])
AC_INIT([nwipe], [0.33], [git@brumit.nl])
AM_INIT_AUTOMAKE(foreign subdir-objects)
AC_OUTPUT(Makefile src/Makefile man/Makefile)
AC_CONFIG_SRCDIR([src/nwipe.c])

View File

@@ -1,4 +1,4 @@
.TH NWIPE "1" "October 2021" "nwipe version 0.32" "User Commands"
.TH NWIPE "1" "March 2022" "nwipe version 0.33" "User Commands"
.SH NAME
nwipe \- securely erase disks
.SH SYNOPSIS
@@ -112,7 +112,12 @@ is5enh \- HMG IS5 enhanced
Filename to log to. Default is STDOUT
.TP
\fB\-p\fR, \fB\-\-prng\fR=\fIMETHOD\fR
PRNG option (mersenne|twister|isaac)
PRNG option (mersenne|twister|isaac|isaac64)
.TP
\fB\-q\fR, \fB\-\-quiet\fR
Anonymize serial numbers, Gui & logs display:
XXXXXXXX = S/N obtained & anonymized.
???????? = S/N not available.
.TP
\fB\-r\fR, \fB\-\-rounds\fR=\fINUM\fR
Number of times to wipe the device using the selected method (default: 1)
@@ -132,4 +137,3 @@ Nwipe is developed by Martijn van Brummelen <github@brumit.nl>
.BR dd (1),
.BR dcfldd (1),
.BR dc3dd (1)

View File

@@ -6,6 +6,5 @@ AM_LDFLAGS =
# this lists the binaries to produce, the (non-PHONY, binary) targets in
# the previous manual Makefile
bin_PROGRAMS = nwipe
nwipe_SOURCES = context.h isaac_rand/isaac_rand.c logging.h options.h prng.h nwipe.c gui.c isaac_rand/isaac_rand.h method.h pass.c device.c gui.h isaac_rand/isaac_standard.h mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c version.h
nwipe_CFLAGS = $(PARTED_CFLAGS)
nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c
nwipe_LDADD = $(PARTED_LIBS)

View File

@@ -34,7 +34,8 @@ typedef enum nwipe_device_t_ {
NWIPE_DEVICE_IEEE1394, // Unimplemented.
NWIPE_DEVICE_ATA,
NWIPE_DEVICE_NVME,
NWIPE_DEVICE_VIRT
NWIPE_DEVICE_VIRT,
NWIPE_DEVICE_SAS
} nwipe_device_t;
typedef enum nwipe_pass_t_ {
@@ -71,6 +72,9 @@ typedef struct nwipe_speedring_t_
#define NWIPE_DEVICE_LABEL_LENGTH 200
#define NWIPE_DEVICE_SIZE_TXT_LENGTH 7
// Arbitary length, so far most paths don't exceed about 25 characters
#define MAX_HWMON_PATH_LENGTH 100
typedef struct nwipe_context_t_
{
/*
@@ -87,7 +91,9 @@ typedef struct nwipe_context_t_
int device_minor; // The minor device number.
int device_part; // The device partition or slice number.
char* device_name; // The device file name.
long long device_size; // The device size in bytes.
char device_name_without_path[100];
char gui_device_name[100];
unsigned 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.
@@ -123,6 +129,21 @@ typedef struct nwipe_context_t_
pthread_t thread; // The ID of the thread.
u64 throughput; // Average throughput in bytes per second.
u64 verify_errors; // The number of verification errors across all passes.
char temp1_path[MAX_HWMON_PATH_LENGTH]; // path to temperature variables /sys/class/hwmon/hwmonX/ etc.
int temp1_crit; // Critical high drive temperature, 1000000=unitialised, millidegree celsius.
int temp1_highest; // Historical highest temperature reached, 1000000=unitialised, millidegree celsius.
int temp1_input; // drive temperature, -1=unitialised. 1000000=unitialised, millidegree celsius.
int temp1_lcrit; // Critical low drive temperature, 1000000=unitialised, millidegree celsius.
int temp1_lowest; // Historically lowest temperature, 1000000=unitialised, millidegree celsius.
int temp1_max; // Maximum allowed temperature, 1000000=unitialised, millidegree celsius.
int temp1_min; // Miniumum allowed temperature, 1000000=unitialised, millidegree celsius.
int temp1_monitored_wipe_max;
int temp1_monitored_wipe_min;
int temp1_monitored_wipe_avg;
int temp1_flash_rate; // number relates to one tenth of a second, so 2 means a flash on and off = 0.4s
int temp1_flash_rate_counter; // used by the gui for timing the flash rate
int temp1_flash_rate_status; // 0=blank 1=visible
time_t temp1_time; // The time when temperature was last checked, seconds since epoch
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

View File

@@ -207,13 +207,34 @@ 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 );
/* full device name, i.e. /dev/sda */
next_device->device_name = dev->path;
/* remove /dev/ from device, right justify and prefix name so string length is eight characters */
nwipe_strip_path( next_device->device_name_without_path, next_device->device_name );
/* To maintain column alignment in the gui we have to remove /dev/ from device names that
* exceed eight characters including the /dev/ path.
*/
if( strlen( next_device->device_name ) > MAX_LENGTH_OF_DEVICE_STRING )
{
strcpy( next_device->gui_device_name, next_device->device_name_without_path );
}
else
{
strcpy( next_device->gui_device_name, next_device->device_name );
}
next_device->device_size = 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. */
/* Attempt to get serial number of device.
*/
next_device->device_serial_no[0] = 0; /* initialise the serial number */
if( ( fd = open( next_device->device_name = dev->path, O_RDONLY ) ) == ERR )
{
nwipe_log( NWIPE_LOG_WARNING, "Unable to open device %s to obtain serial number", next_device->device_name );
@@ -251,6 +272,19 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
}
}
/* Does the user want to anonymize serial numbers ? */
if( nwipe_options.quiet )
{
if( next_device->device_serial_no[0] == 0 )
{
strcpy( next_device->device_serial_no, "???????????????" );
}
else
{
strcpy( next_device->device_serial_no, "XXXXXXXXXXXXXXX" );
}
}
/* All device strings should be 4 characters, prefix with space if under 4 characters */
switch( next_device->device_type )
{
@@ -289,13 +323,17 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
case NWIPE_DEVICE_VIRT:
strcpy( next_device->device_type_str, "VIRT" );
break;
case NWIPE_DEVICE_SAS:
strcpy( next_device->device_type_str, " SAS" );
break;
}
if( strlen( (const char*) next_device->device_serial_no ) )
{
snprintf( next_device->device_label,
NWIPE_DEVICE_LABEL_LENGTH,
"%s %s (%s) %s/%s",
"%s %s [%s] %s/%s",
next_device->device_name,
next_device->device_type_str,
next_device->device_size_text,
@@ -306,7 +344,7 @@ 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] %s",
next_device->device_name,
next_device->device_type_str,
next_device->device_size_text,
@@ -325,7 +363,7 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
return 1;
}
/* Remove leading/training whitespace from a string and left justify result */
/* Remove leading/trailing whitespace from a string and left justify result */
char* trim( char* str )
{
size_t len = 0;
@@ -393,7 +431,7 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
* 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
* 5 = smartctl detected unsupported USB to IDE/SATA adapter
* 6 = All other errors !
*
*/
@@ -406,6 +444,8 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
int device_len;
int set_return_value;
int exit_status;
int idx;
int idx2;
char readlink_command[] = "readlink /sys/block/%s";
char readlink_command2[] = "/usr/bin/readlink /sys/block/%s";
@@ -417,6 +457,10 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
char result[512];
char final_cmd_readlink[sizeof( readlink_command ) + sizeof( device_shortform )];
char final_cmd_smartctl[sizeof( smartctl_command ) + 256];
char* pResult;
char smartctl_labels_to_anonymize[][18] = {
"serial number:", "lu wwn device id:", "logical unit id:", "" /* Don't remove this empty string !, important */
};
/* Initialise return value */
set_return_value = 0;
@@ -464,7 +508,7 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
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. */
/* Return immediately if --nousb specified. Readlink is a requirement for this option. */
if( nwipe_options.nousb )
{
return set_return_value;
@@ -616,19 +660,100 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
/* Read the output a line at a time - output it. */
while( fgets( result, sizeof( result ) - 1, fp ) != NULL )
{
/* Convert the label, i.e everything before the ':' to lower case, it's required to
* convert to lower case as smartctl seems to use inconsistent case when labeling
* for serial number, i.e mostly it produces labels "Serial Number:" but occasionaly
* it produces a label "Serial number:" */
idx = 0;
while( result[idx] != 0 && result[idx] != ':' )
{
/* If upper case alpha character, change to lower case */
if( result[idx] >= 'A' && result[idx] <= 'Z' )
{
result[idx] += 32;
}
idx++;
}
if( nwipe_options.verbose && result[0] != 0x0A )
{
strip_CR_LF( result );
/* Remove serial number if -q option specified */
if( nwipe_options.quiet )
{
/* initialise index into string array */
idx2 = 0;
while( smartctl_labels_to_anonymize[idx2][0] != 0 )
{
if( ( pResult = strstr( result, &smartctl_labels_to_anonymize[idx2][0] ) ) != 0 )
{
/* set index to character after end of label string */
idx = strlen( &smartctl_labels_to_anonymize[idx2][0] );
/* Ignore spaces, overwrite other characters */
while( *( pResult + idx ) != 0x0A && *( pResult + idx ) != 0x0D
&& *( pResult + idx ) != 0 && idx <= sizeof( result ) - 1 )
{
if( *( pResult + idx ) == ' ' )
{
idx++;
continue;
}
else
{
/* ignore if the serial number has been written over with '?' */
if( *( pResult + idx ) != '?' )
{
*( pResult + idx ) = 'X';
}
idx++;
}
}
}
idx2++;
}
}
nwipe_log( NWIPE_LOG_DEBUG, "smartctl: %s", result );
}
if( strstr( result, "Serial Number:" ) != 0 )
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 );
}
if( *bus == 0 )
{
if( strstr( result, "transport protocol:" ) != 0 )
{
/* strip any leading or trailing spaces and left justify, +4 is the length of "bus type:" */
trim( &result[19] );
if( strncmp( &result[19], "sas", 3 ) == 0 )
{
*bus = NWIPE_DEVICE_SAS;
}
}
if( strstr( result, "sata version is:" ) != 0 )
{
/* strip any leading or trailing spaces and left justify, +4 is the length of "bus type:" */
trim( &result[16] );
if( strncmp( &result[16], "sata", 4 ) == 0 )
{
*bus = NWIPE_DEVICE_ATA;
}
}
}
}
/* close */
@@ -655,11 +780,11 @@ int nwipe_get_device_bus_type_and_serialno( char* device, nwipe_device_t* bus, c
if( exit_status == 1 )
{
nwipe_log( NWIPE_LOG_WARNING, "%s USB bridge, no passthru support", device );
nwipe_log( NWIPE_LOG_WARNING, "%s USB bridge, no pass-through support", device );
if( *bus == NWIPE_DEVICE_USB )
{
strcpy( serialnumber, "(no ATA pass thru)" );
strcpy( serialnumber, "(S/N: unknown)" );
set_return_value = 5;
}
}
@@ -687,7 +812,7 @@ void strip_CR_LF( char* str )
void remove_ATA_prefix( char* str )
{
/* Remove "ATA " prefix if present in the model no. string, left justifing string */
/* Remove "ATA" prefix if present in the model no. string, left justifing string */
int idx_pre = 4;
int idx_post = 0;

View File

@@ -23,6 +23,8 @@
#ifndef DEVICE_H_
#define DEVICE_H_
#define MAX_LENGTH_OF_DEVICE_STRING 8
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.
@@ -30,5 +32,6 @@ 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* );
char* trim( char* );
#endif /* DEVICE_H_ */

400
src/gui.c
View File

@@ -42,6 +42,7 @@
#include "pass.h"
#include "logging.h"
#include "version.h"
#include "temperature.h"
#define NWIPE_GUI_PANE 8
@@ -250,6 +251,12 @@ void nwipe_init_pairs( void )
/* Set black on yellow for warning messages */
init_pair( 10, COLOR_BLACK, COLOR_YELLOW );
/* Set black on blue for minimum temperature reached */
init_pair( 11, COLOR_BLACK, COLOR_BLUE );
/* Set blue on blue to make temperature invisible */
init_pair( 12, COLOR_BLUE, COLOR_BLUE );
/* Set the background style. */
wbkgdset( stdscr, COLOR_PAIR( 1 ) | ' ' );
}
@@ -394,6 +401,9 @@ void nwipe_gui_create_main_window()
void nwipe_gui_create_header_window()
{
char anon_label[] = " (ANONYMIZED)";
char bannerplus[80];
/* Create the header window. */
header_window = newwin( NWIPE_GUI_HEADER_H, NWIPE_GUI_HEADER_W, NWIPE_GUI_HEADER_Y, NWIPE_GUI_HEADER_X );
header_panel = new_panel( header_window );
@@ -412,8 +422,16 @@ void nwipe_gui_create_header_window()
/* Clear the header window. */
werase( header_window );
/* If in anonymized mode modify the title banner to reflect this */
strcpy( bannerplus, banner );
if( nwipe_options.quiet )
{
strcat( bannerplus, anon_label );
}
/* Print the product banner. */
nwipe_gui_title( header_window, banner );
nwipe_gui_title( header_window, bannerplus );
/* Refresh the header window */
wnoutrefresh( header_window );
@@ -619,6 +637,18 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
stdscr_lines_previous = stdscr_lines;
stdscr_cols_previous = stdscr_cols;
time_t temperature_check_time = time( NULL );
/* Used in the selection loop to trap a failure of the timeout(), getch() mechanism to block for the designated
* period */
int iteration_counter;
/* Used in the selection loop to trap a failure of the timeout(), getch() mechanism to block for the designated
* period */
int expected_iterations;
time_t previous_iteration_timestamp;
do
{
@@ -720,30 +750,57 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
{
case NWIPE_SELECT_TRUE:
wprintw( main_window, " [wipe] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
if( nwipe_options.method == &nwipe_verify_zero || nwipe_options.method == &nwipe_verify_one )
{
wprintw( main_window,
"[vrfy] %s %s [%s] ",
c[i + offset]->gui_device_name,
c[i + offset]->device_type_str,
c[i + offset]->device_size_text );
}
else
{
wprintw( main_window,
"[wipe] %s %s [%s] ",
c[i + offset]->gui_device_name,
c[i + offset]->device_type_str,
c[i + offset]->device_size_text );
}
break;
case NWIPE_SELECT_FALSE:
/* Print an element that is not selected. */
wprintw( main_window, " [ ] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
wprintw( main_window,
"[ ] %s %s [%s] ",
c[i + offset]->gui_device_name,
c[i + offset]->device_type_str,
c[i + offset]->device_size_text );
break;
case NWIPE_SELECT_TRUE_PARENT:
/* This element will be wiped when its parent is wiped. */
wprintw( main_window, " [****] %i. %s", ( i + offset + 1 ), c[i + offset]->device_label );
wprintw( main_window,
"[****] %s %s [%s] ",
c[i + offset]->gui_device_name,
c[i + offset]->device_type_str,
c[i + offset]->device_size_text );
break;
case NWIPE_SELECT_FALSE_CHILD:
/* 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 );
wprintw( main_window,
"[----] %s %s [%s] ",
c[i + offset]->gui_device_name,
c[i + offset]->device_type_str,
c[i + offset]->device_size_text );
break;
case NWIPE_SELECT_DISABLED:
/* We don't know how to wipe this device. (Iomega Zip drives.) */
wprintw( main_window, " [????] %s", "Unrecognized Device" );
wprintw( main_window, "[????] %s ", "Unrecognized Device" );
break;
default:
@@ -752,6 +809,15 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
break;
} /* switch select */
/* Read the drive temperature values */
nwipe_update_temperature( c[i + offset] );
/* print the temperature */
wprintw_temperature( c[i + offset] );
/* print the drive model and serial number */
wprintw( main_window, "%s/%s", c[i + offset]->device_model, c[i + offset]->device_serial_no );
}
else
{
@@ -791,21 +857,64 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
/* Output to physical screen */
doupdate();
/* Wait 250ms for input from getch, if nothing getch will then continue,
* This is necessary so that the while loop can be exited by the
* terminate_signal e.g.. the user pressing control-c to exit.
* Do not change this value, a higher value means the keys become
* sluggish, any slower and more time is spent unnecessarily looping
* which wastes CPU cycles.
*/
/* Initialise the iteration counter */
iteration_counter = 0;
previous_iteration_timestamp = time( NULL );
/* Calculate Maximum allowed iterations per second */
expected_iterations = ( 1000 / GETCH_BLOCK_MS ) * 2;
do
{
/* Wait 250ms for input from getch, if nothing getch will then continue,
* This is necessary so that the while loop can be exited by the
* terminate_signal e.g.. the user pressing control-c to exit.
* Do not change this value, a higher value means the keys become
* sluggish, any slower and more time is spent unnecessarily looping
* which wastes CPU cycles.
*/
validkeyhit = 0;
timeout( 250 ); // block getch() for 250ms.
timeout( GETCH_BLOCK_MS ); // block getch() for ideally about 250ms.
keystroke = getch(); // Get user input.
timeout( -1 ); // Switch back to blocking mode.
/* To avoid 100% CPU usage, check for a runaway condition caused by the "keystroke = getch(); (above), from
* immediately returning an error condition. We check for an error condition because getch() returns a ERR
* value when the timeout value "timeout( 250 );" expires as well as when a real error occurs. We can't
* differentiate from normal operation and a failure of the getch function to block for the specified period
* of timeout. So here we check the while loop hasn't exceeded the number of expected iterations per second
* ie. a timeout(250) block value of 250ms means we should not see any more than (1000/250) = 4 iterations.
* We double this to 8 to allow a little tolerance. Why is this necessary? It's been found that in KDE
* konsole and other terminals based on the QT terminal engine exiting the terminal without first existing
* nwipe results in nwipe remaining running but detached from any interface which causes getch to fail and
* its associated timeout. So the CPU or CPU core rises to 100%. Here we detect that failure and exit nwipe
* gracefully with the appropriate error. This does not affect use of tmux for attaching or detaching from a
* running nwipe session when sitting at the selection screen. All other terminals correctly terminate nwipe
* when the terminal itself is exited.
*/
iteration_counter++;
if( previous_iteration_timestamp == time( NULL ) )
{
if( iteration_counter > expected_iterations )
{
nwipe_log( NWIPE_LOG_ERROR,
"GUI.c,nwipe_gui_select(), loop runaway, did you close the terminal without exiting "
"nwipe? Initiating shutdown now." );
/* Issue signal to nwipe to shutdown immediately but gracefully */
terminate_signal = 1;
}
}
else
{
/* new second, so reset counter */
iteration_counter = 0;
previous_iteration_timestamp = time( NULL );
}
/* 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
@@ -1180,6 +1289,13 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
* this change and exits the valid key hit loop so the windows can be updated */
getmaxyx( stdscr, stdscr_lines, stdscr_cols );
/* Update the selection window every 60 seconds specifically so that the drive temperatures are updated */
if( time( NULL ) > ( temperature_check_time + 60 ) )
{
temperature_check_time = time( NULL );
validkeyhit = 1;
}
} /* key hit loop */
while( validkeyhit == 0 && terminate_signal != 1 && stdscr_cols_previous == stdscr_cols
&& stdscr_lines_previous == stdscr_lines );
@@ -1413,10 +1529,11 @@ void nwipe_gui_prng( void )
extern nwipe_prng_t nwipe_twister;
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
extern int terminate_signal;
/* The number of implemented PRNGs. */
const int count = 2;
const int count = 3;
/* The first tabstop. */
const int tab1 = 2;
@@ -1446,6 +1563,10 @@ void nwipe_gui_prng( void )
{
focus = 1;
}
if( nwipe_options.prng == &nwipe_isaac64 )
{
focus = 2;
}
do
{
@@ -1455,15 +1576,16 @@ void nwipe_gui_prng( void )
nwipe_gui_create_all_windows_on_terminal_resize( 0, selection_footer );
/* Initialize the working row. */
yy = 2;
yy = 3;
/* Print the options. */
mvwprintw( main_window, yy++, tab1, " %s", nwipe_twister.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_isaac.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_isaac64.label );
mvwprintw( main_window, yy++, tab1, "" );
/* Print the cursor. */
mvwaddch( main_window, 2 + focus, tab1, ACS_RARROW );
mvwaddch( main_window, 3 + focus, tab1, ACS_RARROW );
switch( focus )
{
@@ -1513,6 +1635,34 @@ void nwipe_gui_prng( void )
yy++,
tab1,
" " );
mvwprintw( main_window,
yy++,
tab1,
"Performs best on a 32-bit CPU. Use ISAAC-64 if this system has a 64-bit CPU." );
break;
case 2:
mvwprintw( main_window,
yy++,
tab1,
"ISAAC-64, by Bob Jenkins, is like 32-bit ISAAC, but with a minimum period of" );
mvwprintw( main_window,
yy++,
tab1,
"2^77 and an expected period of 2^16583. It is difficult to recover the " );
mvwprintw( main_window,
yy++,
tab1,
"initial PRNG state by cryptanalysis of the ISAAC-64 stream. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
mvwprintw( main_window,
yy++,
tab1,
"Performs best on a 64-bit CPU. Use ISAAC if this system has a 32-bit CPU. " );
break;
} /* switch */
@@ -1571,6 +1721,10 @@ void nwipe_gui_prng( void )
{
nwipe_options.prng = &nwipe_isaac;
}
if( focus == 2 )
{
nwipe_options.prng = &nwipe_isaac64;
}
return;
case KEY_BACKSPACE:
@@ -1740,10 +1894,6 @@ void nwipe_gui_verify( void )
{
nwipe_options.verify = focus;
}
if( nwipe_options.verify != NWIPE_VERIFY_NONE )
{
nwipe_options.noblank = 0;
}
return;
case KEY_BACKSPACE:
@@ -2030,7 +2180,7 @@ void nwipe_gui_method( void )
mvwprintw( main_window, 5, tab2, "that the rounds option does not apply to this " );
mvwprintw( main_window, 6, tab2, "method. This method always runs one round. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "There is no publically available evidence that " );
mvwprintw( main_window, 8, tab2, "There is no publicly available evidence that " );
mvwprintw( main_window, 9, tab2, "data can be recovered from a modern traditional " );
mvwprintw( main_window, 10, tab2, "hard drive (HDD) that has been zero wiped, " );
mvwprintw( main_window, 11, tab2, "however a wipe that includes a prng may be " );
@@ -2133,7 +2283,7 @@ void nwipe_gui_method( void )
mvwprintw( main_window, 2, tab2, "Security Level: Not applicable" );
mvwprintw( main_window, 4, tab2, "This method only reads the device and checks " );
mvwprintw( main_window, 5, tab2, "that it is all ones (0xFF). " );
mvwprintw( main_window, 5, tab2, "that it is all ones (0xFF)." );
break;
@@ -2392,6 +2542,20 @@ void* nwipe_gui_status( void* ptr )
/* Set to 1 initially to start loop. */
int nwipe_active = 1;
/* Used in the gui status loop to trap a failure of the halfdelay(), getch() mechanism to block for the designated
* period */
int expected_iterations;
/* Used in the selection loop to trap a failure of the timeout(), getch() mechanism to block for the designated
* period, initialise the counter */
int iteration_counter = 0;
time_t previous_iteration_timestamp = time( NULL );
/* Calculate Maximum allowed iterations per second (typically 20), which is double the expected iterations
* (typically 10) */
expected_iterations = ( 1000 / GETCH_GUI_STATS_UPDATE_MS ) * 2;
if( nwipe_time_start == 0 )
{
/* This is the first time that we have been called. */
@@ -2410,10 +2574,41 @@ void* nwipe_gui_status( void* ptr )
* 2. By keeping the delay below 0.2 seconds, i.e 0.1, it makes the keypress and resizing
* nice and responsive.
*/
halfdelay( 1 ); // Important, don't change this unless you know what you are doing ! Related to getch().
halfdelay( GETCH_GUI_STATS_UPDATE_MS ); // Important, don't change this unless you know what you are doing !
// Related to getch().
keystroke = getch(); // Get user input.
iteration_counter++;
/* Much like the same check we perform in the nwipe_gui_select() function, here we check that we are not looping
* any faster than as defined by the halfdelay() function above, typically this loop runs at 10 times a second.
* This check makes sure that if the loop runs faster than double this value i.e 20 times a second then the
* program exits. This check is therefore determining whether the getch() function is returning immediately
* rather than blocking for the defined period of 100ms. Why is this necessary? Some terminals (konsole &
* deriviatives) that are exited while nwipe is still running fail to terminate nwipe this causes the
* halfdelay()/getch() functions to immediately fail causing the loop frequency to drastically increase. We
* detect that speed increase here and therefore close down nwipe. This doesn't affect the use of the tmux
* terminal by which you can detach and reattach to running nwipe processes. tmux still works correctly.
*/
if( previous_iteration_timestamp == time( NULL ) )
{
if( iteration_counter > expected_iterations )
{
nwipe_log( NWIPE_LOG_ERROR,
"GUI.c,nwipe_gui_status(), loop runaway, did you close the terminal without exiting "
"nwipe? Initiating shutdown now." );
/* Issue signal to nwipe to shutdown immediately but gracefully */
terminate_signal = 1;
}
}
else
{
/* new second, so reset counter */
iteration_counter = 0;
previous_iteration_timestamp = time( NULL );
}
/* Get the current time. */
if( nwipe_active && terminate_signal != 1 )
{
@@ -2604,8 +2799,8 @@ void* nwipe_gui_status( void* ptr )
}
}
/* Update screen if not blanked. */
if( nwipe_gui_blank == 0 )
/* Update data in statistics & main windows only if we're in 'gui' mode and only if a wipe has started */
if( nwipe_gui_blank == 0 && global_wipe_status == 1 )
{
if( terminate_signal != 1 )
@@ -2616,8 +2811,16 @@ void* nwipe_gui_status( void* ptr )
/* Print information for the user. */
for( i = offset; i < offset + slots && i < count; i++ )
{
/* Print the device label. */
mvwprintw( main_window, yy++, 2, "%s", c[i]->device_label );
/* Print the device details. */
mvwprintw( main_window,
yy++,
2,
"%s %s [%s] ",
c[i]->device_name,
c[i]->device_type_str,
c[i]->device_size_text );
wprintw_temperature( c[i] );
wprintw( main_window, "%s/%s", c[i]->device_model, c[i]->device_serial_no );
/* Check whether the child process is still running the wipe. */
if( c[i]->wipe_status == 1 )
@@ -2657,11 +2860,11 @@ void* nwipe_gui_status( void* ptr )
if( c[i]->verify_errors )
{
wprintw( main_window, "[verify errors: %llu] ", c[i]->verify_errors );
wprintw( main_window, "[verr:%llu] ", c[i]->verify_errors );
}
if( c[i]->pass_errors )
{
wprintw( main_window, "[pass errors: %llu] ", c[i]->pass_errors );
wprintw( main_window, "[perr:%llu] ", c[i]->pass_errors );
}
if( c[i]->wipe_status == 1 )
{
@@ -2885,18 +3088,18 @@ int compute_stats( void* ptr )
/* 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 )
/* Only update the estimated remaining runtime if the
* throughput for a given drive is greater than 100,000 bytes per second
* This prevents enormous ETA's being calculated on an unresponsive
* drive */
if( c[i]->throughput > 100000 )
{
c[i]->throughput = 1;
}
c[i]->eta = ( c[i]->round_size - c[i]->round_done ) / c[i]->throughput;
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;
if( c[i]->eta > nwipe_misc_thread_data->maxeta )
{
nwipe_misc_thread_data->maxeta = c[i]->eta;
}
}
}
@@ -2918,6 +3121,12 @@ int compute_stats( void* ptr )
nwipe_misc_thread_data->errors += c[i]->verify_errors;
nwipe_misc_thread_data->errors += c[i]->fsyncdata_errors;
/* Read the drive temperature values */
if( nwipe_time_now > ( c[i]->temp1_time + 60 ) )
{
nwipe_update_temperature( c[i] );
}
} /* for statistics */
return nwipe_active;
@@ -2943,7 +3152,7 @@ void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_bytes,
speedring->bytestotal -= speedring->bytes[speedring->position];
speedring->timestotal -= speedring->times[speedring->position];
/* Put the lastest bytes-per-second sample into the ring buffer. */
/* Put the latest bytes-per-second sample into the ring buffer. */
speedring->bytes[speedring->position] = speedring_bytes - speedring->byteslast;
speedring->times[speedring->position] = speedring_now - speedring->timeslast;
@@ -2987,3 +3196,112 @@ int spinner( nwipe_context_t** ptr, int device_idx )
return 0;
}
void temp1_flash( nwipe_context_t* c )
{
if( c->temp1_flash_rate_counter < c->temp1_flash_rate )
{
c->temp1_flash_rate_counter++;
}
else
{
c->temp1_flash_rate_counter = 0;
if( c->temp1_flash_rate_status == 0 )
{
c->temp1_flash_rate_status = 1;
}
else
{
c->temp1_flash_rate_status = 0;
}
}
}
void wprintw_temperature( nwipe_context_t* c )
{
/* If available, print the current temperature. This function determines
* whether the temperature should be printed as white, solid red, flashing red
* solid black or flashing black and then prints it to the main_window.
*/
if( c->temp1_input != 1000000 )
{
/* if drive temperature has exceeded critical continuous running
* temperature && critical value is valid
*/
if( c->temp1_input >= c->temp1_crit && c->temp1_crit != 1000000 )
{
temp1_flash( c );
if( c->temp1_flash_rate_status == 0 )
{
/* blue on blue */
wattron( main_window, COLOR_PAIR( 12 ) );
wprintw( main_window, "[%dC] ", c->temp1_input );
wattroff( main_window, COLOR_PAIR( 12 ) );
}
else
{
/* red on blue */
wattron( main_window, COLOR_PAIR( 3 ) );
wprintw( main_window, "[%dC] ", c->temp1_input );
wattroff( main_window, COLOR_PAIR( 3 ) );
}
}
else
{
/* if drive temperature has exceeded maximum continuous running
* temperature && max value is valid
*/
if( c->temp1_input >= c->temp1_max && c->temp1_max != 1000000 )
{
/* red on blue */
wattron( main_window, COLOR_PAIR( 3 ) );
wprintw( main_window, "[%dC] ", c->temp1_input );
wattroff( main_window, COLOR_PAIR( 3 ) );
}
else
{
/* if drive temperature is below the critical temperature && critical value is valid */
if( c->temp1_input <= c->temp1_lcrit && c->temp1_lcrit != 1000000 )
{
temp1_flash( c );
if( c->temp1_flash_rate_status == 0 )
{
/* blue on blue */
wattron( main_window, COLOR_PAIR( 12 ) );
wprintw( main_window, "[%dC] ", c->temp1_input );
wattroff( main_window, COLOR_PAIR( 12 ) );
}
else
{
/* black on blue */
wattron( main_window, COLOR_PAIR( 11 ) );
wprintw( main_window, "[%dC] ", c->temp1_input );
wattroff( main_window, COLOR_PAIR( 11 ) );
}
}
else
{
/* if drive temperature is below the minimum continuous running temperature && minimum
* value is valid */
if( c->temp1_input <= c->temp1_min && c->temp1_min != 1000000 )
{
/* black on blue */
wattron( main_window, COLOR_PAIR( 11 ) );
wprintw( main_window, "[%dC] ", c->temp1_input );
wattroff( main_window, COLOR_PAIR( 11 ) );
}
else
{
/* Default white on blue */
wprintw( main_window, "[%dC] ", c->temp1_input );
}
}
}
}
}
else
{
wprintw( main_window, "[--C] " );
}
}

View File

@@ -42,10 +42,21 @@ 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
void temp1_flash( nwipe_context_t* ); // toggles term1_flash_status, which flashes the temperature
void wprintw_temperature( nwipe_context_t* );
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
/* Note Do not change unless you understand how this value affects keyboard response and screen refresh when
* the drive selection screen is displayed. (prior to wipe starting). */
#define GETCH_BLOCK_MS 250 /* millisecond block time for getch() */
/* Note The value of 1 (100ms) is the ideal speed for screen refresh during a wipe, a value of 2 is noticably slower,
* don't change unless you understand how this value affects keyboard responsiveness and speed of screen stats/spinner
* updating */
#define GETCH_GUI_STATS_UPDATE_MS 1 /* 1 * 100 = 1/10/sec = millisecond block time for gui stats screen updates */
#endif /* GUI_H_ */

119
src/isaac_rand/isaac64.c Normal file
View File

@@ -0,0 +1,119 @@
/*
------------------------------------------------------------------------------
isaac64.c: My random number generator for 64-bit machines.
By Bob Jenkins, 1996. Public Domain.
------------------------------------------------------------------------------
*/
#ifndef STANDARD
#include "isaac_standard.h"
#endif
#ifndef ISAAC64
#include "isaac64.h"
#endif
#define ind(mm,x) (*(ub8 *)((ub1 *)(mm) + ((x) & ((RANDSIZ-1)<<3))))
#define rngstep(mix,a,b,mm,m,m2,r,x) \
{ \
x = *m; \
a = (mix) + *(m2++); \
*(m++) = y = ind(mm,x) + a + b; \
*(r++) = b = ind(mm,y>>RANDSIZL) + x; \
}
void isaac64(rand64ctx *ctx)
{
register ub8 a,b,x,y,*m,*mm,*m2,*r,*mend;
mm=ctx->mm; r=ctx->randrsl;
a = ctx->aa; b = ctx->bb + (++ctx->cc);
for (m = mm, mend = m2 = m+(RANDSIZ/2); m<mend; )
{
rngstep(~(a^(a<<21)), a, b, mm, m, m2, r, x);
rngstep( a^(a>>5) , a, b, mm, m, m2, r, x);
rngstep( a^(a<<12) , a, b, mm, m, m2, r, x);
rngstep( a^(a>>33) , a, b, mm, m, m2, r, x);
}
for (m2 = mm; m2<mend; )
{
rngstep(~(a^(a<<21)), a, b, mm, m, m2, r, x);
rngstep( a^(a>>5) , a, b, mm, m, m2, r, x);
rngstep( a^(a<<12) , a, b, mm, m, m2, r, x);
rngstep( a^(a>>33) , a, b, mm, m, m2, r, x);
}
ctx->bb = b; ctx->aa = a;
}
#define mix(a,b,c,d,e,f,g,h) \
{ \
a-=e; f^=h>>9; h+=a; \
b-=f; g^=a<<9; a+=b; \
c-=g; h^=b>>23; b+=c; \
d-=h; a^=c<<15; c+=d; \
e-=a; b^=d>>14; d+=e; \
f-=b; c^=e<<20; e+=f; \
g-=c; d^=f>>17; f+=g; \
h-=d; e^=g<<14; g+=h; \
}
void rand64init(rand64ctx *ctx, word flag)
{
word i;
ub8 a,b,c,d,e,f,g,h;
ub8 *mm, *randrsl;
ctx->aa = ctx->bb = ctx->cc = (ub8)0;
mm=ctx->mm;
randrsl=ctx->randrsl;
a=b=c=d=e=f=g=h=0x9e3779b97f4a7c13LL; /* the golden ratio */
for (i=0; i<4; ++i) /* scramble it */
{
mix(a,b,c,d,e,f,g,h);
}
for (i=0; i<RANDSIZ; i+=8) /* fill in mm[] with messy stuff */
{
if (flag) /* use all the information in the seed */
{
a+=randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3];
e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+7];
}
mix(a,b,c,d,e,f,g,h);
mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
}
if (flag)
{ /* do a second pass to make all of the seed affect all of mm */
for (i=0; i<RANDSIZ; i+=8)
{
a+=mm[i ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3];
e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7];
mix(a,b,c,d,e,f,g,h);
mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d;
mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h;
}
}
isaac64(ctx); /* fill in the first set of results */
ctx->randcnt=RANDSIZ; /* prepare to use the first set of results */
}
#ifdef NEVER
int main()
{
ub8 i,j;
rand64ctx ctx;
ctx.aa=ctx.bb=ctx.cc=(ub8)0;
for (i=0; i<RANDSIZ; ++i) ctx.mm[i]=(ub8)0;
rand64init(&ctx, TRUE);
for (i=0; i<2; ++i)
{
isaac64(&ctx);
for (j=0; j<RANDSIZ; ++j)
{
printf("%.8lx%.8lx",(ub4)(ctx.randrsl[j]>>32),(ub4)ctx.randrsl[j]);
if ((j&3)==3) printf("\n");
}
}
}
#endif

41
src/isaac_rand/isaac64.h Normal file
View File

@@ -0,0 +1,41 @@
/*
------------------------------------------------------------------------------
isaac64.h: definitions for a random number generator
Bob Jenkins, 1996, Public Domain
------------------------------------------------------------------------------
*/
#ifndef ISAAC64
#define ISAAC64
#include "isaac_standard.h"
struct rand64ctx
{
ub8 randrsl[RANDSIZ], randcnt;
ub8 mm[RANDSIZ];
ub8 aa, bb, cc;
};
typedef struct rand64ctx rand64ctx;
/*
------------------------------------------------------------------------------
If (flag==TRUE), then use the contents of randrsl[0..255] as the seed.
------------------------------------------------------------------------------
*/
void rand64init(rand64ctx *r, word flag);
void isaac64(rand64ctx *ctx);
/*
------------------------------------------------------------------------------
Call rand64() to retrieve a single 64-bit random value
------------------------------------------------------------------------------
*/
#define isaac64_rand() \
(!(r)->randcnt-- ? \
(isaac64(r), (r)->randcnt=RANDSIZ-1, (r)->randrsl[(r)->>randcnt]) : \
(r)->randrsl[(r)->randcnt])
#endif /* ISAAC64 */

View File

@@ -10,14 +10,10 @@ MODIFIED:
010626: note this is public domain
------------------------------------------------------------------------------
*/
#ifndef STANDARD
#include "isaac_standard.h"
#endif
#ifndef RAND
#define RAND
#define RANDSIZL (4) /* I recommend 8 for crypto, 4 for simulations */
#define RANDSIZ (1<<RANDSIZL)
#include "isaac_standard.h"
/* context of random number generator */
struct randctx

View File

@@ -54,4 +54,7 @@ typedef int word; /* fastest type available */
#define FALSE 0
#define SUCCESS 0 /* 1 on VAX */
#define RANDSIZL (8) /* I recommend 8 for crypto, 4 for simulations */
#define RANDSIZ (1<<RANDSIZL)
#endif /* STANDARD */

View File

@@ -51,6 +51,9 @@ void nwipe_log( nwipe_log_t level, const char* format, ... )
*
*/
extern int terminate_signal;
extern int user_abort;
char** result;
char* malloc_result;
char message_buffer[MAX_LOG_LINE_CHARS * sizeof( char )];
@@ -326,57 +329,64 @@ void nwipe_log( nwipe_log_t level, const char* format, ... )
/* Open the log file for appending. */
fp = fopen( nwipe_options.logfile, "a" );
if( fp == NULL )
if( fp != NULL )
{
fprintf( stderr, "nwipe_log: Unable to open '%s' for logging.\n", nwipe_options.logfile );
/* Get the file descriptor of the log file. */
fd = fileno( fp );
/* Block and lock. */
r = flock( fd, LOCK_EX );
if( r != 0 )
{
perror( "nwipe_log: flock:" );
fprintf( stderr, "nwipe_log: Unable to lock '%s' for logging.\n", nwipe_options.logfile );
r = pthread_mutex_unlock( &mutex1 );
if( r != 0 )
{
fprintf( stderr, "nwipe_log: pthread_mutex_unlock failed. Code %i \n", r );
/* Unlock the file. */
r = flock( fd, LOCK_UN );
fclose( fp );
return;
}
}
fprintf( fp, "%s\n", log_lines[log_current_element] );
/* Unlock the file. */
r = flock( fd, LOCK_UN );
if( r != 0 )
{
perror( "nwipe_log: flock:" );
fprintf( stderr, "Error: Unable to unlock '%s' after logging.\n", nwipe_options.logfile );
}
/* Close the stream. */
r = fclose( fp );
if( r != 0 )
{
perror( "nwipe_log: fclose:" );
fprintf( stderr, "Error: Unable to close '%s' after logging.\n", nwipe_options.logfile );
}
}
else
{
/* Tell user we can't create/open the log and terminate nwipe */
fprintf(
stderr, "\nERROR:Unable to create/open '%s' for logging, permissions?\n\n", nwipe_options.logfile );
r = pthread_mutex_unlock( &mutex1 );
if( r != 0 )
{
fprintf( stderr, "nwipe_log: pthread_mutex_unlock failed. Code %i \n", r );
return;
}
}
/* Get the file descriptor of the log file. */
fd = fileno( fp );
/* Block and lock. */
r = flock( fd, LOCK_EX );
if( r != 0 )
{
perror( "nwipe_log: flock:" );
fprintf( stderr, "nwipe_log: Unable to lock '%s' for logging.\n", nwipe_options.logfile );
r = pthread_mutex_unlock( &mutex1 );
if( r != 0 )
{
fprintf( stderr, "nwipe_log: pthread_mutex_unlock failed. Code %i \n", r );
/* Unlock the file. */
r = flock( fd, LOCK_UN );
fclose( fp );
return;
}
}
fprintf( fp, "%s\n", log_lines[log_current_element] );
/* Unlock the file. */
r = flock( fd, LOCK_UN );
if( r != 0 )
{
perror( "nwipe_log: flock:" );
fprintf( stderr, "Error: Unable to unlock '%s' after logging.\n", nwipe_options.logfile );
}
/* Close the stream. */
r = fclose( fp );
if( r != 0 )
{
perror( "nwipe_log: fclose:" );
fprintf( stderr, "Error: Unable to close '%s' after logging.\n", nwipe_options.logfile );
user_abort = 1;
terminate_signal = 1;
return;
}
}
@@ -498,29 +508,36 @@ int nwipe_log_sysinfo()
* be logged, making sure the last entry in the array is a NULL string. To remove
* an entry simply comment out the keyword with //
*/
char dmidecode_keywords[][24] = {
"bios-version",
"bios-release-date",
"system-manufacturer",
"system-product-name",
"system-version",
"system-serial-number",
"system-uuid",
"baseboard-manufacturer",
"baseboard-product-name",
"baseboard-version",
"baseboard-serial-number",
"baseboard-asset-tag",
"chassis-manufacturer",
"chassis-type",
"chassis-version",
"chassis-serial-number",
"chassis-asset-tag",
"processor-family",
"processor-manufacturer",
"processor-version",
"processor-frequency",
"" // terminates the keyword array. DO NOT REMOVE
/* The 0/1 after the keyword determines whether the data for this
* keyword is displayed when -q (anonymize) has been specified
* by the user. An quick reminder about multi dimensional arrays, the first
* []=the keyword (0-21) including the empty string. The second [] is the
* 1 or 0 value (0 or 1). The third [] is the index value into either string.
*/
char dmidecode_keywords[][2][24] = {
{ "bios-version", "1" },
{ "bios-release-date", "1" },
{ "system-manufacturer", "1" },
{ "system-product-name", "1" },
{ "system-version", "1" },
{ "system-serial-number", "0" },
{ "system-uuid", "0" },
{ "baseboard-manufacturer", "1" },
{ "baseboard-product-name", "1" },
{ "baseboard-version", "1" },
{ "baseboard-serial-number", "0" },
{ "baseboard-asset-tag", "0" },
{ "chassis-manufacturer", "1" },
{ "chassis-type", "1" },
{ "chassis-version", "1" },
{ "chassis-serial-number", "0" },
{ "chassis-asset-tag", "0" },
{ "processor-family", "1" },
{ "processor-manufacturer", "1" },
{ "processor-version", "1" },
{ "processor-frequency", "1" },
{ "", "" } // terminates the keyword array. DO NOT REMOVE
};
char dmidecode_command[] = "dmidecode -s %s";
@@ -563,9 +580,9 @@ int nwipe_log_sysinfo()
{
/* Run the dmidecode command to retrieve each dmidecode keyword, one at a time */
while( dmidecode_keywords[keywords_idx][0] != 0 )
while( dmidecode_keywords[keywords_idx][0][0] != 0 )
{
sprintf( cmd, p_dmidecode_command, &dmidecode_keywords[keywords_idx][0] );
sprintf( cmd, p_dmidecode_command, &dmidecode_keywords[keywords_idx][0][0] );
fp = popen( cmd, "r" );
if( fp == NULL )
{
@@ -581,7 +598,22 @@ int nwipe_log_sysinfo()
{
path[len - 1] = 0;
}
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0], path );
if( nwipe_options.quiet )
{
if( *( &dmidecode_keywords[keywords_idx][1][0] ) == '0' )
{
nwipe_log(
NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], "XXXXXXXXXXXXXXX" );
}
else
{
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
}
}
else
{
nwipe_log( NWIPE_LOG_NOTICE, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
}
}
/* close */
r = pclose( fp );
@@ -607,7 +639,7 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
int i;
int idx_src;
int idx_dest;
char device[7];
char device[18];
char status[9];
char throughput[13];
char total_throughput_string[13];
@@ -662,7 +694,7 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "" );
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
"******************************** Error Summary *********************************" );
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "! Device | Pass Errors | Verifications Errors | Fdatasync I\\O Errors" );
nwipe_log( NWIPE_LOG_NOTIMESTAMP, "! Device | Pass Errors | Verifications Errors | Fdatasync I\\O Errors" );
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
"--------------------------------------------------------------------------------" );
@@ -675,11 +707,8 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
}
else
{
if( c[i]->wipe_status == 0 )
{
strncpy( exclamation_flag, " ", 1 );
exclamation_flag[1] = 0;
}
strncpy( exclamation_flag, " ", 1 );
exclamation_flag[1] = 0;
}
/* Device name, strip any prefixed /dev/.. leaving up to 6 right justified
@@ -691,19 +720,8 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
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_strip_path( device, c[i]->device_name );
nwipe_log( NWIPE_LOG_NOTIMESTAMP,
"%s %s | %10llu | %10llu | %10llu",
exclamation_flag,
@@ -729,44 +747,28 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
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, "! 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 |
* "! sdb |--FAIL--| 120MB/s | 01:22:01 | WD6788.8488YNHj/ZX677888388-N "
* ); " sdc | 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
/* Device name, strip any prefixed /dev/.. leaving up to 8 right justified
* characters eg " sda", prefixed with space to 8 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--;
nwipe_strip_path( device, c[i]->device_name );
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 )
if( c[i]->pass_errors != 0 || c[i]->verify_errors != 0 || c[i]->fsyncdata_errors != 0 )
{
strncpy( exclamation_flag, "!", 1 );
exclamation_flag[1] = 0;
@@ -776,44 +778,32 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
}
else
{
if( c[i]->pass_errors != 0 || c[i]->verify_errors != 0 )
if( c[i]->wipe_status == 0 )
{
strncpy( exclamation_flag, "!", 1 );
strncpy( exclamation_flag, " ", 1 );
exclamation_flag[1] = 0;
strncpy( status, "-FAILED-", 8 );
strncpy( status, " Erased ", 8 );
status[8] = 0;
}
else
{
if( c[i]->wipe_status == 0 )
if( user_abort == 1 )
{
strncpy( exclamation_flag, " ", 1 );
strncpy( exclamation_flag, "!", 1 );
exclamation_flag[1] = 0;
strncpy( status, " Erased ", 8 );
strncpy( status, "UABORTED", 8 );
status[8] = 0;
}
else
{
if( user_abort == 1 )
{
strncpy( exclamation_flag, "!", 1 );
exclamation_flag[1] = 0;
/* If this ever happens, there is a bug ! */
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;
}
strncpy( status, "INSANITY", 8 );
status[8] = 0;
}
}
}
@@ -869,7 +859,7 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
/* 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 */
/* Blank abbreviations used in summary table B=blank, NB=no blank */
if( nwipe_options.noblank )
{
strcpy( blank, "NB" );
@@ -879,7 +869,7 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected )
strcpy( blank, "B" );
}
/* Verify abreviations used in summary table */
/* Verify abbreviations used in summary table */
switch( nwipe_options.verify )
{
case NWIPE_VERIFY_NONE:
@@ -986,3 +976,32 @@ void convert_seconds_to_hours_minutes_seconds( u64 total_seconds, int* hours, in
}
}
}
int nwipe_strip_path( char* output, char* input )
{
/* Take the input string, say "/dev/sda" and remove the "/dev/", prefix the result
* with 'length' spaces. So if length=8 and input=/dev/sda, output will
* be " sda", a string 8 characters long right justified with spaces.
*/
int idx_dest;
int idx_src;
idx_dest = 8;
// idx_dest = length;
output[idx_dest--] = 0;
idx_src = strlen( input );
idx_src--;
while( idx_dest >= 0 )
{
/* if the device name contains a / start prefixing spaces */
if( input[idx_src] == '/' )
{
output[idx_dest--] = ' ';
continue;
}
if( idx_src >= 0 )
{
output[idx_dest--] = input[idx_src--];
}
}
}

View File

@@ -47,5 +47,6 @@ 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* );
int nwipe_strip_path( char*, char* );
#endif /* LOGGING_H_ */

View File

@@ -408,18 +408,6 @@ void* nwipe_gutmann( void* ptr )
/* set wipe in progress flag for GUI */
c->wipe_status = 1;
/* A result buffer. */
int r;
/* The number of patterns in the Guttman Wipe, also used to index the 'patterns' array. */
int i = 35;
/* An index into the 'book' array. */
int j;
/* The N-th element that has not been used. */
int n;
/* Define the Gutmann method. */
nwipe_pattern_t book[] = { { -1, "" }, // Random pass.
{ -1, "" }, // Random pass.
@@ -462,11 +450,10 @@ void* nwipe_gutmann( void* ptr )
nwipe_pattern_t patterns[36];
/* An entropy buffer. */
u16 s[i];
u16 s[27];
/* Load the array with random characters. */
r = read( c->entropy_fd, &s, sizeof( s ) );
ssize_t r = read( c->entropy_fd, &s, sizeof( s ) );
if( r != sizeof( s ) )
{
r = errno;
@@ -486,14 +473,19 @@ void* nwipe_gutmann( void* ptr )
}
}
while( --i >= 0 )
// First 4 random passes
for( int i = 0; i <= 3; ++i )
{
patterns[i] = book[i];
}
// Middle 27 passes in random order
for( int i = 26; i >= 0; --i )
{
/* Get a random integer that is less than the first index 'i'. */
n = (int) ( (double) ( s[i] ) / (double) ( 0x0000FFFF + 1 ) * (double) ( i + 1 ) );
int n = (int) ( (double) ( s[i] ) / (double) ( 0x0000FFFF + 1 ) * (double) ( i + 1 ) );
/* Initialize the secondary index. */
j = -1;
int j = 3;
while( n-- >= 0 )
{
@@ -508,11 +500,16 @@ void* nwipe_gutmann( void* ptr )
}
/* Copy the element. */
patterns[i] = book[j];
patterns[i + 4] = book[j];
/* Mark this element as having been used. */
book[j].length = 0;
}
// Last 4 random passes
for( int i = 31; i <= 34; ++i )
{
patterns[i] = book[i];
}
/* Ensure that the array is terminated. */
patterns[35].length = 0;
@@ -804,9 +801,7 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
/* For the selected method, calculate the correct round_size value (for correct percentage calculation) */
calculate_round_size( c );
c->result = c->round_size;
/* If only verifing then the round size is the device size */
/* If only verifying then the round size is the device size */
if( nwipe_options.method == &nwipe_verify_zero || nwipe_options.method == &nwipe_verify_one )
{
c->round_size = c->device_size;
@@ -1307,7 +1302,7 @@ void calculate_round_size( nwipe_context_t* c )
c->round_size += c->device_size;
}
/* As no final zero blanking pass is permitted by this standard reduce round size if it's seelected */
/* As no final zero blanking pass is permitted by this standard reduce round size if it's selected */
if( nwipe_options.noblank == 0 )
{
/* Reduce for blanking pass */

View File

@@ -41,6 +41,7 @@
#include "device.h"
#include "logging.h"
#include "gui.h"
#include "temperature.h"
#include <sys/ioctl.h> /* FIXME: Twice Included */
#include <sys/shm.h>
@@ -60,9 +61,17 @@ int main( int argc, char** argv )
int nwipe_enumerated; // The number of contexts that have been enumerated.
int nwipe_error = 0; // An error counter.
int nwipe_selected = 0; // The number of contexts that have been selected.
int any_threads_still_running; // used in wipe thread cancellation wait loop
int thread_timeout_counter; // timeout thread cancellation after THREAD_CANCELLATION_TIMEOUT seconds
pthread_t nwipe_gui_thread = 0; // The thread ID of the GUI thread.
pthread_t nwipe_sigint_thread; // The thread ID of the sigint handler.
char modprobe_command[] = "modprobe %s";
char modprobe_command2[] = "/sbin/modprobe %s";
char modprobe_command3[] = "/usr/sbin/modprobe %s";
char module_shortform[50];
char final_cmd_modprobe[sizeof( modprobe_command ) + sizeof( module_shortform )];
/* The entropy source file handle. */
int nwipe_entropy;
@@ -91,7 +100,7 @@ int main( int argc, char** argv )
/* 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 */
/* Initialise flags that indicate whether a fatal or non fatal error occurred on ANY drive */
int fatal_errors_flag = 0;
int non_fatal_errors_flag = 0;
@@ -107,11 +116,18 @@ int main( int argc, char** argv )
/* Parse command line options. */
nwipe_optind = nwipe_options_parse( argc, argv );
if( nwipe_optind == argc )
{
/* File names were not given by the user. Scan for devices. */
nwipe_enumerated = nwipe_device_scan( &c1 );
if( terminate_signal == 1 )
{
cleanup();
exit( 1 );
}
if( nwipe_enumerated == 0 )
{
nwipe_log( NWIPE_LOG_INFO,
@@ -202,6 +218,53 @@ int main( int argc, char** argv )
pthread_create( &nwipe_sigint_thread, &pthread_attr, signal_hand, &nwipe_thread_data_ptr );
}
/* Makesure the drivetemp module is loaded, else drives hwmon entries won't appear in /sys/class/hwmon */
final_cmd_modprobe[0] = 0;
/* The kernel module we are going to load */
strcpy( module_shortform, "drivetemp" );
/* Determine whether we can access modprobe, required if the PATH environment is not setup ! (Debian sid 'su' as
* opposed to 'su -' */
if( system( "which modprobe > /dev/null 2>&1" ) )
{
if( system( "which /sbin/modprobe > /dev/null 2>&1" ) )
{
if( system( "which /usr/sbin/modprobe > /dev/null 2>&1" ) )
{
nwipe_log( NWIPE_LOG_WARNING, "modprobe command not found. Install kmod package (modprobe)) !" );
nwipe_log( NWIPE_LOG_WARNING, "Most temperature monitoring may be unavailable as module drivetemp" );
nwipe_log( NWIPE_LOG_WARNING, "could not be loaded. drivetemp is not available on kernels < v5.5" );
}
else
{
sprintf( final_cmd_modprobe, modprobe_command3, module_shortform );
}
}
else
{
sprintf( final_cmd_modprobe, modprobe_command2, module_shortform );
}
}
else
{
sprintf( final_cmd_modprobe, modprobe_command, module_shortform );
}
/* load the drivetemp module */
if( system( final_cmd_modprobe ) != 0 )
{
nwipe_log( NWIPE_LOG_WARNING, "hwmon: Unable to load module drivetemp, temperatures may be unavilable." );
nwipe_log( NWIPE_LOG_WARNING, "hwmon: It's possible the drivetemp software isn't modular but built-in" );
nwipe_log( NWIPE_LOG_WARNING, "hwmon: to the kernel, as is the case with ShredOS.x86_64 in which case" );
nwipe_log( NWIPE_LOG_WARNING, "hwmon: the temperatures will actually be available despite this issue." );
}
else
{
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Module drivetemp loaded, drive temperatures available" );
}
/* A context struct for each device has already been created. */
/* Now set specific nwipe options */
for( i = 0; i < nwipe_enumerated; i++ )
@@ -223,12 +286,21 @@ int main( int argc, char** argv )
/* The user must manually select devices. */
c1[i]->select = NWIPE_SELECT_FALSE;
}
/* Initialise temperature variables for device */
nwipe_init_temperature( c1[i] );
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Device %s hwmon path = %s", c1[i]->device_name, c1[i]->temp1_path );
}
nwipe_update_temperature( c1[i] );
}
/* Check for initialization errors. */
if( nwipe_error )
{
nwipe_log( NWIPE_LOG_ERROR, "Initialization eror %i\n", nwipe_error );
nwipe_log( NWIPE_LOG_ERROR, "Initialization error %i\n", nwipe_error );
cleanup();
return -1;
}
@@ -271,6 +343,9 @@ int main( int argc, char** argv )
{
nwipe_selected += 1;
}
/* Initialise the wipe result value */
c1[i]->result = 0;
}
/* Pass the number selected to the struct for other threads */
@@ -422,7 +497,7 @@ int main( int argc, char** argv )
if( c2[i]->device_size == 0 )
{
nwipe_log( NWIPE_LOG_ERROR,
"%s, sect/blk/dev %llu/%i/%llu",
"%s, sect/blk/dev %i/%i/%llu",
c2[i]->device_name,
c2[i]->device_sector_size,
c2[i]->device_block_size,
@@ -433,7 +508,7 @@ int main( int argc, char** argv )
else
{
nwipe_log( NWIPE_LOG_NOTICE,
"%s, sect/blk/dev %llu/%i/%llu",
"%s, sect/blk/dev %i/%i/%llu",
c2[i]->device_name,
c2[i]->device_sector_size,
c2[i]->device_block_size,
@@ -521,7 +596,6 @@ int main( int argc, char** argv )
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 );
}
@@ -543,9 +617,12 @@ int main( int argc, char** argv )
{
nwipe_log( NWIPE_LOG_WARNING, "main()>pthread_join():Error when waiting for GUI thread to cancel." );
}
if( nwipe_options.verbose )
else
{
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" );
}
}
}
@@ -556,26 +633,86 @@ int main( int argc, char** argv )
}
/* Now join the wipe threads and wait until they have terminated */
for( i = 0; i < nwipe_selected; i++ )
any_threads_still_running = 1;
thread_timeout_counter = THREAD_CANCELLATION_TIMEOUT;
while( any_threads_still_running )
{
if( c2[i]->thread )
/* quit waiting if we've tried 'thread_timeout_counter' times */
if( thread_timeout_counter == 0 )
{
/* Joins the thread and waits for completion before continuing */
r = pthread_join( c2[i]->thread, NULL );
if( r != 0 )
{
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 */
break;
}
if( nwipe_options.verbose )
any_threads_still_running = 0;
for( i = 0; i < nwipe_selected; i++ )
{
if( c2[i]->thread )
{
nwipe_log( NWIPE_LOG_INFO, "Wipe thread for device %s has been cancelled", c2[i]->device_name );
}
printf( "\nWaiting for wipe thread to cancel for %s\n", c2[i]->device_name );
/* Close the device file descriptor. */
close( c2[i]->device_fd );
/* Joins the thread and waits for completion before continuing */
r = pthread_join( c2[i]->thread, NULL );
if( r != 0 )
{
nwipe_log( NWIPE_LOG_ERROR,
"Error joining the wipe thread when waiting for thread to cancel.",
c2[i]->device_name );
if( r == EDEADLK )
{
nwipe_log( NWIPE_LOG_ERROR,
"Error joining the wipe thread: EDEADLK: Deadlock detected.",
c2[i]->device_name );
}
else
{
if( r == EINVAL )
{
nwipe_log( NWIPE_LOG_ERROR,
"Error joining the wipe thread: %s EINVAL: thread is not joinable.",
c2[i]->device_name );
}
else
{
if( r == ESRCH )
{
nwipe_log( NWIPE_LOG_ERROR,
"Error joining the wipe thread: %s ESRCH: no matching thread found",
c2[i]->device_name );
}
}
}
any_threads_still_running = 1;
}
else
{
c2[i]->thread = 0; /* Zero the thread so we know it's been cancelled */
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_INFO, "Wipe thread for device %s has terminated", c2[i]->device_name );
}
/* Close the device file descriptor. */
close( c2[i]->device_fd );
}
}
}
thread_timeout_counter--;
sleep( 1 );
}
if( nwipe_options.verbose )
{
for( i = 0; i < nwipe_selected; i++ )
{
nwipe_log( NWIPE_LOG_DEBUG,
"Status: %s, result=%d, pass_errors=%llu, verify_errors=%llu, fsync_errors=%llu",
c2[i]->device_name,
c2[i]->result,
c2[i]->pass_errors,
c2[i]->verify_errors,
c2[i]->fsyncdata_errors );
}
}
@@ -592,25 +729,35 @@ int main( int argc, char** argv )
{
for( i = 0; i < nwipe_selected; i++ )
{
/* Check for non-fatal errors. */
if( c2[i]->result > 0 )
/* Check for errors. */
if( c2[i]->result != 0 || c2[i]->pass_errors != 0 || c2[i]->verify_errors != 0
|| c2[i]->fsyncdata_errors != 0 )
{
nwipe_log( NWIPE_LOG_FATAL, "Nwipe exited with non fatal errors on device = %s\n", c2[i]->device_name );
/* If the run_method ever returns anything other than zero then makesure there is at least one pass
* error This is so that the log summary tables correctly show a failure when one occurs as it only
* shows pass, verification and fdatasync errors. */
if( c2[i]->result != 0 )
{
if( c2[i]->pass_errors == 0 )
{
c2[i]->pass_errors = 1;
}
}
nwipe_log( NWIPE_LOG_FATAL,
"Nwipe exited with errors on device = %s, see log for specific error\n",
c2[i]->device_name );
nwipe_log( NWIPE_LOG_DEBUG,
"Status: %s, result=%d, pass_errors=%llu, verify_errors=%llu, fsync_errors=%llu",
c2[i]->device_name,
c2[i]->result,
c2[i]->pass_errors,
c2[i]->verify_errors,
c2[i]->fsyncdata_errors );
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;
}
}
}
/* Generate and send the drive status summary to the log */

View File

@@ -76,13 +76,6 @@ 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;
int log_elements_allocated = 0;
int log_elements_displayed = 0;
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; */
/* Ncurses headers. */
#ifdef NCURSES_IN_SUBDIR
#include <ncurses/ncurses.h>
@@ -113,6 +106,8 @@ typedef unsigned char u8;
#define BLKBSZSET _IOW( 0x12, 113, size_t )
#define BLKGETSIZE64 _IOR( 0x12, 114, sizeof( u64 ) )
#define THREAD_CANCELLATION_TIMEOUT 10
/* This is required for ioctl FDFLUSH. */
#include <linux/fd.h>

View File

@@ -40,6 +40,7 @@ int nwipe_options_parse( int argc, char** argv )
extern nwipe_prng_t nwipe_twister;
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
/* The getopt() result holder. */
int nwipe_opt;
@@ -53,7 +54,7 @@ int nwipe_options_parse( int argc, char** argv )
int i;
/* The list of acceptable short options. */
char nwipe_options_short[] = "Vvhl:m:p:r:e:";
char nwipe_options_short[] = "Vvhl:m:p:qr:e:";
/* The list of acceptable long options. */
static struct option nwipe_options_long[] = {
@@ -93,10 +94,13 @@ int nwipe_options_parse( int argc, char** argv )
/* Whether to allow signals to interrupt a wipe. */
{ "nosignals", no_argument, 0, 0 },
/* Whether to exit after wiping or wait for a keypress. */
/* Whether to display the gui. */
{ "nogui", no_argument, 0, 0 },
/* A flag to indicate whether the devices whould be opened in sync mode. */
/* Whether to anonymize the serial numbers. */
{ "quiet", no_argument, 0, 'q' },
/* A flag to indicate whether the devices would be opened in sync mode. */
{ "sync", required_argument, 0, 0 },
/* Verify that wipe patterns are being written to the device. */
@@ -115,13 +119,14 @@ int nwipe_options_parse( int argc, char** argv )
nwipe_options.autonuke = 0;
nwipe_options.autopoweroff = 0;
nwipe_options.method = &nwipe_dodshort;
nwipe_options.prng = &nwipe_twister;
nwipe_options.prng = ( sizeof( unsigned long int ) >= 8 ) ? &nwipe_isaac64 : &nwipe_isaac;
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.quiet = 0;
nwipe_options.sync = DEFAULT_SYNC_RATE;
nwipe_options.verbose = 0;
nwipe_options.verify = NWIPE_VERIFY_LAST;
@@ -371,10 +376,21 @@ int nwipe_options_parse( int argc, char** argv )
break;
}
if( strcmp( optarg, "isaac64" ) == 0 )
{
nwipe_options.prng = &nwipe_isaac64;
break;
}
/* Else we do not know this PRNG. */
fprintf( stderr, "Error: Unknown prng '%s'.\n", optarg );
exit( EINVAL );
case 'q': /* Anonymize serial numbers */
nwipe_options.quiet = 1;
break;
case 'r': /* Rounds option. */
if( sscanf( optarg, " %i", &nwipe_options.rounds ) != 1 || nwipe_options.rounds < 1 )
@@ -413,6 +429,7 @@ void nwipe_options_log( void )
{
extern nwipe_prng_t nwipe_twister;
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
/**
* Prints a manifest of options to the log.
@@ -472,11 +489,19 @@ void nwipe_options_log( void )
}
else
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Undefined" );
if( nwipe_options.prng == &nwipe_isaac64 )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac64" );
}
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, " quiet = %i", nwipe_options.quiet );
nwipe_log( NWIPE_LOG_NOTICE, " rounds = %i", nwipe_options.rounds );
nwipe_log( NWIPE_LOG_NOTICE, " sync = %i", nwipe_options.sync );
@@ -542,10 +567,13 @@ void display_help()
puts( " random / prng / stream - PRNG Stream" );
puts( " zero / quick - Overwrite with zeros" );
puts( " one - Overwrite with ones (0xFF)" );
puts( " verify_zero - Verifies disk is zero filled\n" );
puts( " verify_zero - Verifies disk is zero filled" );
puts( " verify_one - Verifies disk is 0xFF filled\n" );
puts( " -l, --logfile=FILE Filename to log to. Default is STDOUT\n" );
puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac)\n" );
puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac|isaac64)\n" );
puts( " -q, --quiet Anonymize logs and the GUI by removing unique data, i.e." );
puts( " serial numbers, LU WWN Device ID, and SMBIOS/DMI data" );
puts( " XXXXXX = S/N exists, ????? = S/N not obtainable\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" );

View File

@@ -60,6 +60,7 @@ typedef struct
char logfile[FILENAME_MAX]; // The filename to log the output to.
char exclude[MAX_NUMBER_EXCLUDED_DRIVES][MAX_DRIVE_PATH_LENGTH]; // Drives excluded from the search.
nwipe_prng_t* prng; // The pseudo random number generator implementation.
int quiet; // Anonymize serial numbers
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

View File

@@ -265,7 +265,7 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE )
}
/* 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 ) */
* to disk in the event of some future undetected bug in a prng or its implementation. */
b = calloc( c->device_stat.st_blksize, sizeof( char ) );
/* Check the memory allocation. */

View File

@@ -24,31 +24,49 @@
#include "mt19937ar-cok/mt19937ar-cok.h"
#include "isaac_rand/isaac_rand.h"
#include "isaac_rand/isaac64.h"
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_isaac64 = { "ISAAC-64 (isaac64.c)", nwipe_isaac64_init, nwipe_isaac64_read };
int nwipe_u32tobuffer( u8* buffer, u32 rand, int len )
/* Print given number of bytes from unsigned integer number to a byte stream buffer starting with low-endian. */
static inline void u32_to_buffer( u8* restrict buffer, u32 val, const int len )
{
/*
* Print given number of bytes from unsigned integer number to a byte stream buffer starting with low-endian.
*/
int i;
u8 c; // single char
if( len > sizeof( u32 ) )
for( int i = 0; i < len; ++i )
{
nwipe_log( NWIPE_LOG_FATAL, "Tried to print longer number than the value passed." );
len = sizeof( u32 );
buffer[i] = ( u8 )( val & 0xFFUL );
val >>= 8;
}
for( i = 0; i < len; i++ )
}
static inline void u64_to_buffer( u8* restrict buffer, u64 val, const int len )
{
for( int i = 0; i < len; ++i )
{
c = rand & 0xFFUL;
rand = rand >> 8;
buffer[i] = c;
buffer[i] = ( u8 )( val & 0xFFULL );
val >>= 8;
}
return 0;
}
static inline u32 isaac_nextval( randctx* restrict ctx )
{
if( ctx->randcnt == 0 )
{
isaac( ctx );
ctx->randcnt = RANDSIZ;
}
ctx->randcnt--;
return ctx->randrsl[ctx->randcnt];
}
static inline u64 isaac64_nextval( rand64ctx* restrict ctx )
{
if( ctx->randcnt == 0 )
{
isaac64( ctx );
ctx->randcnt = RANDSIZ;
}
ctx->randcnt--;
return ctx->randrsl[ctx->randcnt];
}
int nwipe_twister_init( NWIPE_PRNG_INIT_SIGNATURE )
@@ -66,23 +84,22 @@ int nwipe_twister_init( NWIPE_PRNG_INIT_SIGNATURE )
int nwipe_twister_read( NWIPE_PRNG_READ_SIGNATURE )
{
u32 i = 0;
u32 ii;
u32 words = count / SIZE_OF_TWISTER; // the values of twister_genrand_int32 is strictly 4 bytes
u32 remain = count % SIZE_OF_TWISTER; // the values of twister_genrand_int32 is strictly 4 bytes
u8* restrict bufpos = buffer;
size_t words = count / SIZE_OF_TWISTER; // the values of twister_genrand_int32 is strictly 4 bytes
/* Twister returns 4-bytes per call, so progress by 4 bytes. */
for( ii = 0; ii < words; ++ii )
for( size_t ii = 0; ii < words; ++ii )
{
nwipe_u32tobuffer( (u8*) ( buffer + i ), twister_genrand_int32( (twister_state_t*) *state ), SIZE_OF_TWISTER );
i = i + SIZE_OF_TWISTER;
u32_to_buffer( bufpos, twister_genrand_int32( (twister_state_t*) *state ), SIZE_OF_TWISTER );
bufpos += SIZE_OF_TWISTER;
}
/* If there is some remainder copy only relevant number of bytes to not
* overflow the buffer. */
const size_t remain = count % SIZE_OF_TWISTER; // SIZE_OF_TWISTER is strictly 4 bytes
if( remain > 0 )
{
nwipe_u32tobuffer( (u8*) ( buffer + i ), twister_genrand_int32( (twister_state_t*) *state ), remain );
u32_to_buffer( bufpos, twister_genrand_int32( (twister_state_t*) *state ), remain );
}
return 0;
@@ -140,30 +157,95 @@ int nwipe_isaac_init( NWIPE_PRNG_INIT_SIGNATURE )
int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE )
{
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
randctx* isaac_state = *state;
u8* restrict bufpos = buffer;
size_t words = count / SIZE_OF_ISAAC; // the values of isaac is strictly 4 bytes
/* Isaac returns 4-bytes per call, so progress by 4 bytes. */
for( ii = 0; ii < words; ++ii )
for( size_t 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;
u32_to_buffer( bufpos, isaac_nextval( isaac_state ), SIZE_OF_ISAAC );
bufpos += SIZE_OF_ISAAC;
}
/* If there is some remainder copy only relevant number of bytes to not overflow the buffer. */
const size_t remain = count % SIZE_OF_ISAAC; // SIZE_OF_ISAAC is strictly 4 bytes
if( remain > 0 )
{
/* get the next 32bit random number */
isaac( isaac_state );
nwipe_u32tobuffer( (u8*) ( buffer + i ), isaac_state->randrsl[0], SIZE_OF_ISAAC );
u32_to_buffer( bufpos, isaac_nextval( isaac_state ), remain );
}
return 0;
}
int nwipe_isaac64_init( NWIPE_PRNG_INIT_SIGNATURE )
{
int count;
rand64ctx* isaac_state = *state;
nwipe_log( NWIPE_LOG_NOTICE, "Initialising ISAAC-64 prng" );
if( *state == NULL )
{
/* This is the first time that we have been called. */
*state = malloc( sizeof( rand64ctx ) );
isaac_state = *state;
/* Check the memory allocation. */
if( isaac_state == 0 )
{
nwipe_perror( errno, __FUNCTION__, "malloc" );
nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the isaac state." );
return -1;
}
}
/* Take the minimum of the isaac seed size and available entropy. */
if( sizeof( isaac_state->randrsl ) < seed->length )
{
count = sizeof( isaac_state->randrsl );
}
else
{
memset( isaac_state->randrsl, 0, sizeof( isaac_state->randrsl ) );
count = seed->length;
}
if( count == 0 )
{
/* Start ISACC without a seed. */
rand64init( isaac_state, 0 );
}
else
{
/* Seed the ISAAC state with entropy. */
memcpy( isaac_state->randrsl, seed->s, count );
/* The second parameter indicates that randrsl is non-empty. */
rand64init( isaac_state, 1 );
}
return 0;
}
int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE )
{
rand64ctx* isaac_state = *state;
u8* restrict bufpos = buffer;
size_t words = count / SIZE_OF_ISAAC64; // the values of ISAAC-64 is strictly 8 bytes
for( size_t ii = 0; ii < words; ++ii )
{
u64_to_buffer( bufpos, isaac64_nextval( isaac_state ), SIZE_OF_ISAAC64 );
bufpos += SIZE_OF_ISAAC64;
}
/* If there is some remainder copy only relevant number of bytes to not overflow the buffer. */
const size_t remain = count % SIZE_OF_ISAAC64; // SIZE_OF_ISAAC64 is strictly 8 bytes
if( remain > 0 )
{
u64_to_buffer( bufpos, isaac64_nextval( isaac_state ), remain );
}
return 0;

View File

@@ -21,6 +21,8 @@
#ifndef PRNG_H_
#define PRNG_H_
#include <sys/types.h>
/* A chunk of random data. */
typedef struct
{
@@ -50,11 +52,14 @@ int nwipe_twister_read( NWIPE_PRNG_READ_SIGNATURE );
/* ISAAC prototypes. */
int nwipe_isaac_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE );
int nwipe_isaac64_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_isaac64_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 */
/* Size of the isaac/isaac64 is not derived from the architecture, but it is strictly 4 or 8 bytes */
#define SIZE_OF_ISAAC 4
#define SIZE_OF_ISAAC64 8
#endif /* PRNG_H_ */

270
src/temperature.c Normal file
View File

@@ -0,0 +1,270 @@
/*
* temperature.c: functions that populate the drive temperature variables
* in each drives context structure.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 2.
*
* 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
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
//#define _LARGEFILE64_SOURCE
//#define _FILE_OFFSET_BITS 64
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <dirent.h>
#include "nwipe.h"
#include "context.h"
#include "method.h"
#include "device.h"
#include "prng.h"
#include "options.h"
#include "device.h"
#include "logging.h"
#include "temperature.h"
int nwipe_init_temperature( nwipe_context_t* c )
{
/* This function is called after each nwipe_context_t has been created.
* It initialises the temperature variables in each context and then
* constructs a path that is placed in the context that points to the
* appropriate /sys/class/hwmon/hwmonX directory that corresponds with
* the particular drive represented in the context structure.
*/
DIR* dir;
DIR* dir2;
const char dirpath[] = "/sys/class/hwmon";
char dirpath_tmp[256];
char dirpath_tmp2[256];
char dirpath_hwmonX[256];
char device[256];
char device_context_name[256];
// const char dirpath[] = "/home/nick/mouse/hwmon1";
struct dirent* dp;
struct dirent* dp2;
/* Why Initialise with 1000000? Because the GUI needs to know whether data
* has been obtained so it can display appropriate information when a
* device is unable to provide temperature data */
c->temp1_crit = 1000000;
c->temp1_highest = 1000000;
c->temp1_input = 1000000;
c->temp1_lcrit = 1000000;
c->temp1_lowest = 1000000;
c->temp1_max = 1000000;
c->temp1_min = 1000000;
c->temp1_monitored_wipe_max = 1000000;
c->temp1_monitored_wipe_min = 1000000;
c->temp1_monitored_wipe_avg = 1000000;
c->temp1_flash_rate = 2;
c->temp1_flash_rate_counter = 0;
c->temp1_path[0] = 0;
c->temp1_time = 0;
/* Each hwmonX directory is processed in turn and once a hwmonX directory has been
* found that is a block device and the block device name matches the drive
* name in the current context then the path to ../hwmonX is constructed and written
* to the drive context structure '* c'. This path is used in the nwipe_update_temperature
* function to retrieve temperature data and store it in the device context
*/
if( ( dir = opendir( dirpath ) ) != NULL )
{
/* Process each hwmonX sub directory in turn */
while( ( dp = readdir( dir ) ) != NULL )
{
/* Does the directory start with 'hwmon' */
if( strstr( dp->d_name, "hwmon" ) != NULL )
{
if( nwipe_options.verbose )
{
/* print a empty line to separate the different hwmon sensors */
nwipe_log( NWIPE_LOG_DEBUG, "hwmon:" );
}
strcpy( dirpath_tmp, dirpath );
strcat( dirpath_tmp, "/" );
strcat( dirpath_tmp, dp->d_name );
strcpy( dirpath_hwmonX, dirpath_tmp );
strcat( dirpath_tmp, "/device/block" );
/* Depending on the class of block device, the device name may
* appear in different sub-directories. So we try to open each
* directory that are known to contain block devices. These are
* /sys/class/hwmon/hwmonX/device/block
* /sys/class/hwmon/hwmonX/device/nvme/nvme0
* /sys/class/hwmon/hwmonX/device/
*/
if( ( dir2 = opendir( dirpath_tmp ) ) == NULL )
{
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_DEBUG, "hwmon: %s doesn't exist, trying next path", dirpath_tmp );
}
strcpy( dirpath_tmp2, dirpath_hwmonX );
strcat( dirpath_tmp2, "/device/nvme/nvme0" );
strcpy( dirpath_tmp, dirpath_tmp2 );
if( ( dir2 = opendir( dirpath_tmp ) ) == NULL )
{
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_DEBUG, "hwmon: %s doesn't exist, trying next path", dirpath_tmp );
}
strcpy( dirpath_tmp2, dirpath_hwmonX );
strcat( dirpath_tmp2, "/device" );
strcpy( dirpath_tmp, dirpath_tmp2 );
if( ( dir2 = opendir( dirpath_tmp ) ) == NULL )
{
if( nwipe_options.verbose )
{
nwipe_log(
NWIPE_LOG_DEBUG, "hwmon: %s doesn't exist, no more paths to try", dirpath_tmp );
}
continue;
}
}
}
if( dir2 != NULL )
{
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_DEBUG, "hwmon: Found %s", dirpath_tmp );
}
/* Read the device name */
while( ( dp2 = readdir( dir2 ) ) != NULL )
{
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_DEBUG, "hwmon: dirpath_tmp=%s/%s", dirpath_tmp, &dp2->d_name[0] );
}
/* Skip the '.' and '..' directories */
if( dp2->d_name[0] == '.' )
{
continue;
}
strcpy( device, dp2->d_name );
/* Create a copy of the device name from the context but strip the path from it, right justify
* device name, prefix with spaces so length is 8. */
nwipe_strip_path( device_context_name, c->device_name );
/* Remove leading/training whitespace from a string and left justify result */
trim( device_context_name );
/* Does the hwmon device match the device for this drive context */
if( strcmp( device, device_context_name ) != 0 )
{
/* No, so try next hwmon device */
continue;
}
else
{
/* Match ! This hwmon device matches this context, so write the hwmonX path to the context
*/
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: %s has temperature monitoring", device, dirpath_tmp );
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_DEBUG, "hwmon: %s found in %s", device, dirpath_tmp );
}
/* Copy the hwmon path to the drive context structure */
strcpy( c->temp1_path, dirpath_hwmonX );
}
}
closedir( dir2 );
}
}
}
closedir( dir );
}
return 0;
}
void nwipe_update_temperature( nwipe_context_t* c )
{
/* For the given drive context obtain the path to it's hwmon temperature settings
* and read then write the temperature values back to the context. A numeric ascii to integer conversion is
* performed. The temperaures should be updated no more frequently than every 60 seconds
*/
char temperature_label[NUMBER_OF_FILES][20] = {
"temp1_crit", "temp1_highest", "temp1_input", "temp1_lcrit", "temp1_lowest", "temp1_max", "temp1_min" };
int* temperature_pcontext[NUMBER_OF_FILES] = {
&( c->temp1_crit ),
&( c->temp1_highest ),
&( c->temp1_input ),
&( c->temp1_lcrit ),
&( c->temp1_lowest ),
&( c->temp1_max ),
&( c->temp1_min ) };
char path[256];
char temperature[256];
FILE* fptr;
int idx;
int result;
for( idx = 0; idx < NUMBER_OF_FILES; idx++ )
{
/* Construct the full path including filename */
strcpy( path, c->temp1_path );
strcat( path, "/" );
strcat( path, &( temperature_label[idx][0] ) );
/* Open the file */
if( ( fptr = fopen( path, "r" ) ) != NULL )
{
/* Acquire data until we reach a newline */
result = fscanf( fptr, "%[^\n]", temperature );
/* Convert numeric ascii to binary integer */
*( temperature_pcontext[idx] ) = atoi( temperature );
/* Divide by 1000 to get degrees celcius */
*( temperature_pcontext[idx] ) = *( temperature_pcontext[idx] ) / 1000;
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: %s %dC", path, *( temperature_pcontext[idx] ) );
}
fclose( fptr );
}
else
{
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Unable to open %s", path );
}
}
}
/* Update the time stamp that records when we checked the temperature,
* this is used by the GUI to check temperatures periodically, typically
* every 60 seconds */
c->temp1_time = time( NULL );
return;
}

30
src/temperature.h Normal file
View File

@@ -0,0 +1,30 @@
/*.
* temperature.h: The header file for disk drive temperature sensing
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 2.
*
* 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
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef TEMPERATURE_H_
#define TEMPERATURE_H_
#include <sys/types.h>
#include "context.h"
int nwipe_init_temperature( nwipe_context_t* );
void nwipe_update_temperature( nwipe_context_t* );
#define NUMBER_OF_FILES 7
#endif /* TEMPERATURE_H_ */

View File

@@ -4,14 +4,14 @@
* used by configure to dynamically assign those values
* to documentation files.
*/
const char* version_string = "0.32";
const char* version_string = "0.33";
const char* program_name = "nwipe";
const char* author_name = "Martijn van Brummelen";
const char* email_address = "git@brumit.nl";
const char* years = "2021";
const char* years = "2022";
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.32";
const char* banner = "nwipe 0.33";