diff --git a/src/Makefile.am b/src/Makefile.am index 2609bdd..9a719ef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 isaac_rand/isaac_rand.c logging.h options.h prng.h version.h temperature.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 temperature.c nwipe_LDADD = $(PARTED_LIBS) diff --git a/src/context.h b/src/context.h index 260d070..b9435cb 100644 --- a/src/context.h +++ b/src/context.h @@ -72,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_ { /* @@ -124,6 +127,17 @@ 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/hwmon2/ etc. + u64 temp1_crit; // Critical high drive temperature, -1=unitialised, millidegree celsius. + u64 temp1_highest; // Historical highest temperature reached, -1=unitialised, millidegree celsius. + u64 temp1_input; // drive temperature, -1=unitialised. -1=unitialised, millidegree celsius. + u64 temp1_lcrit; // Critical low drive temperature, -1=unitialised, millidegree celsius. + u64 temp1_lowest; // Historically lowest temperature, -1=unitialised, millidegree celsius. + u64 temp1_max; // Maximum allowed temperature, -1=unitialised, millidegree celsius. + u64 temp1_min; // Miniumum allowed temperature, -1=unitialised, millidegree celsius. + u64 temp1_monitored_wipe_max; + u64 temp1_monitored_wipe_min; + u64 temp1_monitored_wipe_avg; 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 diff --git a/src/device.h b/src/device.h index e6b6d4f..ebff165 100644 --- a/src/device.h +++ b/src/device.h @@ -30,5 +30,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_ */ diff --git a/src/logging.c b/src/logging.c index 19f3a2e..d0bb99a 100644 --- a/src/logging.c +++ b/src/logging.c @@ -691,19 +691,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, @@ -743,24 +732,8 @@ void nwipe_log_summary( nwipe_context_t** ptr, int nwipe_selected ) * characters eg " sda", prefixed with space to 6 characters, note that * we are processing the strings right to left */ - idx_dest = 6; - device[idx_dest--] = 0; - idx_src = strlen( c[i]->device_name ); - idx_src--; + 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, @@ -986,3 +959,28 @@ void convert_seconds_to_hours_minutes_seconds( u64 total_seconds, int* hours, in } } } + +int nwipe_strip_path( char* output, char* input ) +{ + int idx_dest; + int idx_src; + idx_dest = 6; + output[idx_dest--] = 0; + // idx_src = strlen( c[i]->device_name ); + 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--]; + } + } +} diff --git a/src/logging.h b/src/logging.h index bba9152..b2d4b75 100644 --- a/src/logging.h +++ b/src/logging.h @@ -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_ */ diff --git a/src/nwipe.c b/src/nwipe.c index 264aa13..6337022 100644 --- a/src/nwipe.c +++ b/src/nwipe.c @@ -41,6 +41,7 @@ #include "device.h" #include "logging.h" #include "gui.h" +#include "temperature.h" #include /* FIXME: Twice Included */ #include @@ -202,6 +203,16 @@ 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 */ + if( system( "modprobe drivetemp" ) != 0 ) + { + nwipe_log( NWIPE_LOG_ERROR, "Unable to load module drivetemp, drive temperatures may not be available" ); + } + else + { + nwipe_log( NWIPE_LOG_NOTICE, "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,6 +234,15 @@ 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, "Device %s hwmon path = %s", c1[i]->device_name, c1[i]->temp1_path ); + } + + nwipe_update_temperature( c1[i] ); } /* Check for initialization errors. */ diff --git a/src/prng.h b/src/prng.h index 34d152a..8b03f5a 100644 --- a/src/prng.h +++ b/src/prng.h @@ -21,6 +21,8 @@ #ifndef PRNG_H_ #define PRNG_H_ +#include + /* A chunk of random data. */ typedef struct { diff --git a/src/temperature.c b/src/temperature.c new file mode 100644 index 0000000..7291909 --- /dev/null +++ b/src/temperature.c @@ -0,0 +1,215 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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_hwmonX[256]; + char device[256]; + char device_context_name[256]; + // const char dirpath[] = "/home/nick/mouse/hwmon1"; + struct dirent* dp; + struct dirent* dp2; + int match; + + /* 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_path[0] = 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 ) + { + while( ( dp = readdir( dir ) ) != NULL ) + { + /* Does the directory start with 'hwmon' */ + + if( strstr( dp->d_name, "hwmon" ) != NULL ) + { + strcpy( dirpath_tmp, dirpath ); + strcat( dirpath_tmp, "/" ); + strcat( dirpath_tmp, dp->d_name ); + strcpy( dirpath_hwmonX, dirpath_tmp ); + strcat( dirpath_tmp, "/device/block" ); + + /* Is this hardware monitor a block device ? i.e. does + * /sys/class/hwmon/hwmonX/device/block exist?*/ + + if( ( dir2 = opendir( dirpath_tmp ) ) != NULL ) + { + /* Read the device name */ + while( ( dp2 = readdir( dir2 ) ) != NULL ) + { + /* 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. */ + 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, "Device %s has \'hwmon\' temperature monitoring", device ); + + /* 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" }; + u64* 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; + + 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] ) ); + + if( nwipe_options.verbose ) + { + nwipe_log( NWIPE_LOG_NOTICE, "hwmon: path=%s", path ); + } + + /* Open the file */ + if( ( fptr = fopen( path, "r" ) ) != NULL ) + { + /* Acquire data until we reach a newline */ + 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; + + fclose( fptr ); + } + else + { + if( nwipe_options.verbose ) + { + nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Unable to open %s", path ); + } + } + } + if( nwipe_options.verbose ) + { + nwipe_log( NWIPE_LOG_NOTICE, + "hwmon: %lluC, %lluC, %lluC, %lluC, %lluC, %lluC, %lluC", + c->temp1_crit, + c->temp1_highest, + c->temp1_input, + c->temp1_lcrit, + c->temp1_lowest, + c->temp1_max, + c->temp1_min ); + } + return; +} diff --git a/src/temperature.h b/src/temperature.h new file mode 100644 index 0000000..d538822 --- /dev/null +++ b/src/temperature.h @@ -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 +#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_ */