mirror of
https://github.com/martijnvanbrummelen/nwipe.git
synced 2026-02-20 13:42:14 +00:00
Merge branch 'v0.15'
This commit is contained in:
5
README
5
README
@@ -14,6 +14,11 @@ Andy Beverley
|
||||
RELEASE NOTES
|
||||
=============
|
||||
|
||||
v0.15
|
||||
=====
|
||||
- Add more detailed information to status page when wiping
|
||||
- Add ability to send SIGUSR1 to print wiping current status to log
|
||||
|
||||
v0.14
|
||||
=====
|
||||
- Added explicit check for ncurses (required for Fedora). See bug 3604008.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.64])
|
||||
AC_INIT(nwipe, 0.14, andy@andybev.com)
|
||||
AM_INIT_AUTOMAKE(nwipe, 0.14)
|
||||
AC_INIT(nwipe, 0.15, andy@andybev.com)
|
||||
AM_INIT_AUTOMAKE(nwipe, 0.15)
|
||||
AC_OUTPUT(Makefile src/Makefile man/Makefile)
|
||||
AC_CONFIG_SRCDIR([src/nwipe.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
@@ -18,6 +18,8 @@ same as dwipe, with a few changes:
|
||||
- The parted library is used to detect drives
|
||||
.TP
|
||||
- The code is designed to be compiled with gcc
|
||||
.TP
|
||||
- SIGUSR1 can be used to log the stats of the current wipe
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
@@ -41,6 +43,7 @@ Do not wait for a key before exiting (default is to wait).
|
||||
\fB\-\-nogui\fR
|
||||
Do not show the GUI interface. Can only be used with the autonuke option.
|
||||
Nowait option is automatically invoked with the nogui option.
|
||||
SIGUSR1 can be used to retrieve the current wiping statistics.
|
||||
.TP
|
||||
\fB\-\-verify\fR=\fITYPE\fR
|
||||
Whether to perform verification of erasure (default: last)
|
||||
|
||||
@@ -123,9 +123,12 @@ typedef struct nwipe_context_t_
|
||||
/* Values cannot form part of the second array below, hence the need for this. */
|
||||
typedef struct
|
||||
{
|
||||
int nwipe_enumerated; /* The number of devices available. */
|
||||
int nwipe_selected; /* The number of devices being wiped. */
|
||||
pthread_t *gui_thread; /* The ID of GUI thread. */
|
||||
int nwipe_enumerated; /* The number of devices available. */
|
||||
int nwipe_selected; /* The number of devices being wiped. */
|
||||
time_t maxeta; /* The estimated runtime of the slowest device. */
|
||||
u64 throughput; /* Total throughput */
|
||||
u64 errors; /* The combined number of errors of all processes. */
|
||||
pthread_t *gui_thread; /* The ID of GUI thread. */
|
||||
} nwipe_misc_thread_data_t;
|
||||
|
||||
/* The second points to the first structure, as well as the structure of all the devices */
|
||||
|
||||
@@ -124,6 +124,8 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
|
||||
next_device->label = dev->model;
|
||||
next_device->device_name = dev->path;
|
||||
next_device->device_size = dev->length * dev->sector_size;
|
||||
/* Attempt to get serial number of device. */
|
||||
ioctl(next_device->device_fd, HDIO_GET_IDENTITY, &next_device->identity);
|
||||
|
||||
(*c)[dcount] = next_device;
|
||||
|
||||
|
||||
145
src/gui.c
145
src/gui.c
@@ -446,35 +446,39 @@ void nwipe_gui_select( int count, nwipe_context_t** c )
|
||||
{
|
||||
case NWIPE_SELECT_TRUE:
|
||||
|
||||
wprintw( main_window, " [wipe] %i. %s - %s (%lld bytes)", (i + offset + 1),
|
||||
wprintw( main_window, " [wipe] %i. %s - %s %s (%lld bytes)", (i + offset + 1),
|
||||
c[i+offset]->device_name,
|
||||
c[i+offset]->label,
|
||||
c[i+offset]->identity.serial_no,
|
||||
c[i+offset]->device_size );
|
||||
break;
|
||||
|
||||
case NWIPE_SELECT_FALSE:
|
||||
/* Print an element that is not selected. */
|
||||
wprintw( main_window, " [ ] %i. %s - %s (%lld bytes)", (i + offset +1),
|
||||
wprintw( main_window, " [ ] %i. %s - %s %s (%lld bytes)", (i + offset +1),
|
||||
c[i+offset]->device_name,
|
||||
c[i+offset]->label,
|
||||
c[i+offset]->identity.serial_no,
|
||||
c[i+offset]->device_size );
|
||||
break;
|
||||
|
||||
case NWIPE_SELECT_TRUE_PARENT:
|
||||
|
||||
/* This element will be wiped when its parent is wiped. */
|
||||
wprintw( main_window, " [****] %i. %s - %s (%lld bytes)", (i + offset +1),
|
||||
wprintw( main_window, " [****] %i. %s - %s %s (%lld bytes)", (i + offset +1),
|
||||
c[i+offset]->device_name,
|
||||
c[i+offset]->label,
|
||||
c[i+offset]->identity.serial_no,
|
||||
c[i+offset]->device_size );
|
||||
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 - %s (%lld bytes)", (i + offset +1),
|
||||
wprintw( main_window, " [----] %i. %s - %s %s (%lld bytes)", (i + offset +1),
|
||||
c[i+offset]->device_name,
|
||||
c[i+offset]->label,
|
||||
c[i+offset]->identity.serial_no,
|
||||
c[i+offset]->device_size );
|
||||
break;
|
||||
|
||||
@@ -1659,13 +1663,13 @@ void *nwipe_gui_status( void *ptr )
|
||||
int keystroke;
|
||||
|
||||
/* The combined througput of all processes. */
|
||||
u64 nwipe_throughput = 0;
|
||||
nwipe_misc_thread_data->throughput = 0;
|
||||
|
||||
/* The estimated runtime of the slowest device. */
|
||||
time_t nwipe_maxeta = 0;
|
||||
nwipe_misc_thread_data->maxeta = 0;
|
||||
|
||||
/* The combined number of errors of all processes. */
|
||||
u64 nwipe_errors = 0;
|
||||
nwipe_misc_thread_data->errors = 0;
|
||||
|
||||
/* Time values. */
|
||||
int nwipe_hh;
|
||||
@@ -1801,59 +1805,22 @@ void *nwipe_gui_status( void *ptr )
|
||||
if ( nwipe_gui_blank == 0 )
|
||||
{
|
||||
|
||||
nwipe_active = 0; // Number of active wipe threads
|
||||
/* Enumerate all contexts to compute statistics. */
|
||||
for( i = 0 ; i < count ; i++ )
|
||||
{
|
||||
/* Check whether the child process is still running the wipe. */
|
||||
if( c[i]->thread > 0 )
|
||||
{
|
||||
/* Increment the child counter. */
|
||||
nwipe_active += 1;
|
||||
|
||||
/* Maintain a rolling average of throughput. */
|
||||
nwipe_update_speedring( &c[i]->speedring, c[i]->round_done, nwipe_time_now );
|
||||
|
||||
if( c[i]->speedring.timestotal > 0 )
|
||||
{
|
||||
/* Update the current average throughput in bytes-per-second. */
|
||||
c[i]->throughput = c[i]->speedring.bytestotal / c[i]->speedring.timestotal;
|
||||
|
||||
/* Update the estimated remaining runtime. */
|
||||
/* Check that throughput is not zero (sometimes caused during a sync) */
|
||||
if (c[i]->throughput == 0)
|
||||
{
|
||||
c[i]->throughput = 1;
|
||||
}
|
||||
|
||||
c[i]->eta = ( c[i]->round_size - c[i]->round_done ) / c[i]->throughput;
|
||||
|
||||
if( c[i]->eta > nwipe_maxeta )
|
||||
{
|
||||
nwipe_maxeta = c[i]->eta;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the percentage value. */
|
||||
c[i]->round_percent = (double) c[i]->round_done / (double) c[i]->round_size * 100;
|
||||
|
||||
/* Accumulate combined throughput. */
|
||||
nwipe_throughput += c[i]->throughput;
|
||||
|
||||
} /* child running */
|
||||
|
||||
/* Accumulate the error count. */
|
||||
nwipe_errors += c[i]->pass_errors;
|
||||
nwipe_errors += c[i]->verify_errors;
|
||||
|
||||
} /* for statistics */
|
||||
|
||||
nwipe_active = compute_stats(ptr); // Returns number of active wipe threads
|
||||
|
||||
/* Print information for the user. */
|
||||
for( i = offset ; i < offset + slots && i < count ; i++ )
|
||||
{
|
||||
/* Print the context label. */
|
||||
mvwprintw( main_window, yy++, 2, "%s", c[i]->label );
|
||||
if ( strlen(c[i]->identity.serial_no) )
|
||||
{
|
||||
mvwprintw( main_window, yy++, 2, "%s - %s (%s)", c[i]->device_name,
|
||||
c[i]->label,
|
||||
c[i]->identity.serial_no);
|
||||
}
|
||||
else {
|
||||
mvwprintw( main_window, yy++, 2, "%s - %s", c[i]->device_name,
|
||||
c[i]->label );
|
||||
}
|
||||
|
||||
/* Check whether the child process is still running the wipe. */
|
||||
if( c[i]->thread > 0 )
|
||||
@@ -1940,6 +1907,7 @@ void *nwipe_gui_status( void *ptr )
|
||||
nwipe_gui_load();
|
||||
|
||||
|
||||
u64 nwipe_throughput = nwipe_misc_thread_data->throughput;
|
||||
if( nwipe_throughput >= INT64_C( 1000000000000000 ) )
|
||||
{ nwipe_throughput /= INT64_C( 1000000000000 ); nwipe_format = nwipe_tera; }
|
||||
else if( nwipe_throughput >= INT64_C( 1000000000000 ) )
|
||||
@@ -1975,6 +1943,7 @@ void *nwipe_gui_status( void *ptr )
|
||||
|
||||
mvwprintw( stats_window, NWIPE_GUI_STATS_ETA_Y, 1, "Remaining:" );
|
||||
|
||||
time_t nwipe_maxeta = nwipe_misc_thread_data->maxeta;
|
||||
if( nwipe_maxeta > 0 )
|
||||
{
|
||||
/* Do it again for the estimated runtime remaining. */
|
||||
@@ -1990,7 +1959,7 @@ void *nwipe_gui_status( void *ptr )
|
||||
|
||||
/* Print the error count. */
|
||||
mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_ERRORS_X, "Errors:" );
|
||||
mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_TAB, "%llu", nwipe_errors );
|
||||
mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_TAB, "%llu", nwipe_misc_thread_data->errors );
|
||||
|
||||
/* Add a border. */
|
||||
box( stats_window, 0, 0 );
|
||||
@@ -2050,6 +2019,70 @@ void *nwipe_gui_status( void *ptr )
|
||||
|
||||
} /* nwipe_gui_status */
|
||||
|
||||
int compute_stats(void *ptr)
|
||||
{
|
||||
nwipe_thread_data_ptr_t *nwipe_thread_data_ptr;
|
||||
nwipe_thread_data_ptr = (nwipe_thread_data_ptr_t *) ptr;
|
||||
|
||||
nwipe_context_t **c;
|
||||
nwipe_misc_thread_data_t *nwipe_misc_thread_data;
|
||||
|
||||
c = nwipe_thread_data_ptr->c;
|
||||
nwipe_misc_thread_data = nwipe_thread_data_ptr->nwipe_misc_thread_data;
|
||||
int count = nwipe_misc_thread_data->nwipe_selected;
|
||||
|
||||
int nwipe_active = 0;
|
||||
int i;
|
||||
|
||||
time_t nwipe_time_now = time( NULL );
|
||||
|
||||
/* Enumerate all contexts to compute statistics. */
|
||||
for( i = 0 ; i < count ; i++ )
|
||||
{
|
||||
/* Check whether the child process is still running the wipe. */
|
||||
if( c[i]->thread > 0 )
|
||||
{
|
||||
/* Increment the child counter. */
|
||||
nwipe_active += 1;
|
||||
|
||||
/* Maintain a rolling average of throughput. */
|
||||
nwipe_update_speedring( &c[i]->speedring, c[i]->round_done, nwipe_time_now );
|
||||
|
||||
if( c[i]->speedring.timestotal > 0 )
|
||||
{
|
||||
/* Update the current average throughput in bytes-per-second. */
|
||||
c[i]->throughput = c[i]->speedring.bytestotal / c[i]->speedring.timestotal;
|
||||
|
||||
/* Update the estimated remaining runtime. */
|
||||
/* Check that throughput is not zero (sometimes caused during a sync) */
|
||||
if (c[i]->throughput == 0)
|
||||
{
|
||||
c[i]->throughput = 1;
|
||||
}
|
||||
|
||||
c[i]->eta = ( c[i]->round_size - c[i]->round_done ) / c[i]->throughput;
|
||||
|
||||
if( c[i]->eta > nwipe_misc_thread_data->maxeta )
|
||||
{
|
||||
nwipe_misc_thread_data->maxeta = c[i]->eta;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the percentage value. */
|
||||
c[i]->round_percent = (double) c[i]->round_done / (double) c[i]->round_size * 100;
|
||||
|
||||
/* Accumulate combined throughput. */
|
||||
nwipe_misc_thread_data->throughput += c[i]->throughput;
|
||||
} /* child running */
|
||||
|
||||
/* Accumulate the error count. */
|
||||
nwipe_misc_thread_data->errors += c[i]->pass_errors;
|
||||
nwipe_misc_thread_data->errors += c[i]->verify_errors;
|
||||
|
||||
} /* for statistics */
|
||||
|
||||
return nwipe_active;
|
||||
}
|
||||
|
||||
void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_bytes, time_t speedring_now )
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ void nwipe_gui_rounds( void ); /* Change the rounds op
|
||||
void nwipe_gui_verify( void ); /* Change the verify option. */
|
||||
void nwipe_gui_noblank( void ); /* Change the noblank option. */
|
||||
|
||||
int compute_stats(void *ptr);
|
||||
void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_done, time_t speedring_now );
|
||||
|
||||
|
||||
|
||||
66
src/nwipe.c
66
src/nwipe.c
@@ -78,6 +78,9 @@ int main( int argc, char** argv )
|
||||
/* Initialised and populated in device scan. */
|
||||
nwipe_context_t **c1 = 0;
|
||||
|
||||
/* The array of pointers to contexts that will actually be wiped. */
|
||||
nwipe_context_t **c2 = (nwipe_context_t **)malloc(nwipe_enumerated * sizeof(nwipe_context_t *));
|
||||
|
||||
/* Parse command line options. */
|
||||
nwipe_optind = nwipe_options_parse( argc, argv );
|
||||
|
||||
@@ -130,6 +133,7 @@ int main( int argc, char** argv )
|
||||
sigaddset(&sigset, SIGTERM);
|
||||
sigaddset(&sigset, SIGQUIT);
|
||||
sigaddset(&sigset, SIGINT);
|
||||
sigaddset(&sigset, SIGUSR1);
|
||||
pthread_sigmask(SIG_SETMASK, &sigset, NULL);
|
||||
|
||||
/* Create a signal handler thread. This thread will catch all */
|
||||
@@ -141,7 +145,7 @@ int main( int argc, char** argv )
|
||||
nwipe_misc_thread_data_t nwipe_misc_thread_data;
|
||||
nwipe_thread_data_ptr_t nwipe_thread_data_ptr;
|
||||
|
||||
nwipe_thread_data_ptr.c = c1;
|
||||
nwipe_thread_data_ptr.c = c2;
|
||||
nwipe_misc_thread_data.nwipe_enumerated = nwipe_enumerated;
|
||||
if( !nwipe_options.nogui )
|
||||
nwipe_misc_thread_data.gui_thread = &nwipe_gui_thread;
|
||||
@@ -225,9 +229,6 @@ int main( int argc, char** argv )
|
||||
/* Pass the number selected to the struct for other threads */
|
||||
nwipe_misc_thread_data.nwipe_selected = nwipe_selected;
|
||||
|
||||
/* The array of pointers to contexts that will actually be wiped. */
|
||||
nwipe_context_t **c2 = (nwipe_context_t **)malloc(nwipe_enumerated * sizeof(nwipe_context_t *));
|
||||
|
||||
/* Populate the array of selected contexts. */
|
||||
for( i = 0, j = 0 ; i < nwipe_enumerated ; i++ )
|
||||
{
|
||||
@@ -287,10 +288,8 @@ int main( int argc, char** argv )
|
||||
}
|
||||
*/
|
||||
|
||||
/* Attempt to get serial number of device. */
|
||||
|
||||
ioctl(c2[i]->device_fd, HDIO_GET_IDENTITY, &c2[i]->identity);
|
||||
if ( c2[i]->identity.serial_no ) {
|
||||
/* Print serial number of device if it exists. */
|
||||
if ( strlen(c2[i]->identity.serial_no) ) {
|
||||
nwipe_log( NWIPE_LOG_INFO, "Device %s has serial number %s", c2[i]->device_name, c2[i]->identity.serial_no);
|
||||
}
|
||||
|
||||
@@ -496,6 +495,7 @@ void *signal_hand(void *ptr)
|
||||
sigaddset(&sigset, SIGTERM);
|
||||
sigaddset(&sigset, SIGQUIT);
|
||||
sigaddset(&sigset, SIGINT);
|
||||
sigaddset(&sigset, SIGUSR1);
|
||||
|
||||
int i;
|
||||
|
||||
@@ -517,13 +517,60 @@ void *signal_hand(void *ptr)
|
||||
|
||||
switch ( sig ) {
|
||||
|
||||
// Log current status. All values are automatically updated by the GUI
|
||||
case SIGUSR1 :
|
||||
{
|
||||
compute_stats(ptr);
|
||||
|
||||
for( i = 0; i < nwipe_misc_thread_data->nwipe_selected; i++ )
|
||||
{
|
||||
|
||||
if ( c[i]->thread )
|
||||
{
|
||||
char *status;
|
||||
switch( c[i]->pass_type )
|
||||
{
|
||||
case NWIPE_PASS_FINAL_BLANK:
|
||||
status = "[blanking]";
|
||||
break;
|
||||
|
||||
case NWIPE_PASS_FINAL_OPS2:
|
||||
status = "[OPS-II final]";
|
||||
break;
|
||||
|
||||
case NWIPE_PASS_WRITE:
|
||||
status = "[writing]";
|
||||
break;
|
||||
|
||||
case NWIPE_PASS_VERIFY:
|
||||
status = "[verifying]";
|
||||
break;
|
||||
|
||||
case NWIPE_PASS_NONE:
|
||||
break;
|
||||
}
|
||||
if( c[i]->sync_status ) { status = "[syncing]"; }
|
||||
nwipe_log( NWIPE_LOG_INFO, "%s: %05.2f%%, round %i of %i, pass %i of %i %s", \
|
||||
c[i]->device_name, c[i]->round_percent, c[i]->round_working, c[i]->round_count, c[i]->pass_working, c[i]->pass_count, status );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( c[i]->result == 0 ) { nwipe_log( NWIPE_LOG_INFO, "%s: Success", c[i]->device_name ); }
|
||||
else if( c[i]->signal ) { nwipe_log( NWIPE_LOG_INFO, "%s: Failure: signal %i", c[i]->device_name, c[i]->signal ); }
|
||||
else { nwipe_log( NWIPE_LOG_INFO, "%s: Failure: code %i", c[i]->device_name, c[i]->result ); }
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SIGHUP :
|
||||
case SIGINT :
|
||||
case SIGQUIT :
|
||||
case SIGTERM :
|
||||
{
|
||||
|
||||
for( i = 0; i < nwipe_misc_thread_data->nwipe_enumerated; i++ )
|
||||
for( i = 0; i < nwipe_misc_thread_data->nwipe_selected; i++ )
|
||||
{
|
||||
|
||||
if ( c[i]->thread )
|
||||
@@ -551,7 +598,6 @@ void *signal_hand(void *ptr)
|
||||
printf("%s\n", log_lines[i]);
|
||||
}
|
||||
|
||||
|
||||
printf("Program interrupted (caught signal %d)\n", sig);
|
||||
|
||||
// Cleanup
|
||||
|
||||
@@ -395,7 +395,7 @@ display_help()
|
||||
puts(" --noblank Do not blank disk after wipe (default is to complete a final blank pass)" );
|
||||
puts(" --nowait Do not wait for a key before exiting (default is to wait)" );
|
||||
puts(" --nogui Do not show the GUI interface. Automatically invokes the nowait option" );
|
||||
puts(" Must be used with --autonuke option");
|
||||
puts(" Must be used with --autonuke option. Send SIGUSR1 to log current stats");
|
||||
puts("");
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* used by configure to dynamically assign those values
|
||||
* to documentation files.
|
||||
*/
|
||||
const char *version_string = "0.14";
|
||||
const char *version_string = "0.15";
|
||||
const char *program_name = "nwipe";
|
||||
const char *author_name = "Andy Beverley";
|
||||
const char *email_address = "andy@andybev.com";
|
||||
|
||||
Reference in New Issue
Block a user