Files
nwipe/src/device.c

264 lines
7.6 KiB
C
Raw Normal View History

2013-09-06 23:38:39 +01:00
/*
* device.c: Device routines for nwipe.
*
* Copyright Darik Horn <dajhorn-dban@vanadac.com>.
2020-01-05 16:27:30 -05:00
*
2013-09-06 23:38:39 +01:00
* Modifications to original dwipe Copyright Andy Beverley <andy@andybev.com>
2020-01-05 16:27:30 -05:00
*
2013-09-06 23:38:39 +01:00
* 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.,
2020-01-05 16:27:30 -05:00
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2013-09-06 23:38:39 +01:00
*
*/
2017-12-06 20:09:47 +01:00
#include <stdint.h>
2013-09-06 23:38:39 +01:00
#include "nwipe.h"
#include "context.h"
#include "method.h"
#include "options.h"
#include "logging.h"
#include <sys/ioctl.h>
2020-01-05 16:27:30 -05:00
#include <linux/hdreg.h> // Drive specific defs
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
2013-09-06 23:38:39 +01:00
#include <parted/parted.h>
2017-12-06 20:09:47 +01:00
#include <parted/debug.h>
2013-09-06 23:38:39 +01:00
int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount );
2020-01-05 16:27:30 -05:00
char* trim( char* str );
2013-09-06 23:38:39 +01:00
int nwipe_device_scan( nwipe_context_t*** c )
{
2020-01-05 16:27:30 -05:00
/**
* Scans the filesystem for storage device names.
*
* @parameter device_names A reference to a null array pointer.
* @modifies device_names Populates device_names with an array of nwipe_contect_t
* @returns The number of strings in the device_names array.
*
*/
PedDevice* dev = NULL;
ped_device_probe_all();
2013-09-06 23:38:39 +01:00
2020-01-05 16:27:30 -05:00
int dcount = 0;
while( ( dev = ped_device_get_next( dev ) ) )
{
if( check_device( c, dev, dcount ) )
dcount++;
}
/* Return the number of devices that were found. */
return dcount;
2013-09-06 23:38:39 +01:00
} /* nwipe_device_scan */
2020-01-05 16:27:30 -05:00
int nwipe_device_get( nwipe_context_t*** c, char** devnamelist, int ndevnames )
2013-09-06 23:38:39 +01:00
{
2020-01-05 16:27:30 -05:00
/**
* Gets information about devices
*
* @parameter device_names A reference to a null array pointer.
* @parameter devnamelist An array of string pointers to the device names
* @parameter ndevnames Number of elements in devnamelist
* @modifies device_names Populates device_names with an array of nwipe_contect_t
* @returns The number of strings in the device_names array.
*
*/
PedDevice* dev = NULL;
int i;
int dcount = 0;
for( i = 0; i < ndevnames; i++ )
{
dev = ped_device_get( devnamelist[i] );
if( !dev )
{
nwipe_log( NWIPE_LOG_WARNING, "Device %s not found", devnamelist[i] );
continue;
}
if( check_device( c, dev, dcount ) )
dcount++;
}
/* Return the number of devices that were found. */
return dcount;
2013-09-06 23:38:39 +01:00
} /* nwipe_device_get */
int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
{
2020-01-05 16:27:30 -05:00
/* Populate this struct, then assign it to overall array of structs. */
nwipe_context_t* next_device;
int fd;
int idx;
/* Check whether this drive is on the excluded drive list ? */
idx = 0;
while( idx < 10 )
{
if( !strcmp( dev->path, nwipe_options.exclude[idx++] ) )
{
nwipe_log( NWIPE_LOG_NOTICE, "Device %s excluded as per command line option -e", dev->path );
return 0;
}
}
/* Try opening the device to see if it's valid. Close on completion. */
if( !ped_device_open( dev ) )
{
nwipe_log( NWIPE_LOG_FATAL, "Unable to open device" );
return 0;
}
ped_device_close( dev );
/* New device, reallocate memory for additional struct pointer */
*c = realloc( *c, ( dcount + 1 ) * sizeof( nwipe_context_t* ) );
next_device = malloc( sizeof( nwipe_context_t ) );
/* Check the allocation. */
if( !next_device )
{
nwipe_perror( errno, __FUNCTION__, "malloc" );
nwipe_log( NWIPE_LOG_FATAL, "Unable to create the array of enumeration contexts." );
return 0;
}
/* Zero the allocation. */
memset( next_device, 0, sizeof( nwipe_context_t ) );
/* Get device information */
next_device->device_model = dev->model;
2020-01-05 16:27:30 -05:00
next_device->device_name = dev->path;
next_device->device_size = dev->length * dev->sector_size;
next_device->device_size_text = ped_unit_format_byte( dev, dev->length * dev->sector_size );
next_device->result = -2;
/* Attempt to get serial number of device. */
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 );
}
/*
* We don't check the ioctl return status because there are plenty of situations where a serial number may not be
* returned by ioctl such as USB drives, logical volumes, encryted volumes, so the log file would have multiple
* benign ioctl errors reported which isn't necessarily a problem.
*/
ioctl( fd, HDIO_GET_IDENTITY, &next_device->identity );
close( fd );
for( idx = 0; idx < 20; idx++ )
{
next_device->device_serial_no[idx] = next_device->identity.serial_no[idx];
}
2020-01-05 16:27:30 -05:00
// Terminate the string.
next_device->device_serial_no[20] = 0;
// Remove leading/trailing whitespace from serial number and left justify.
trim( (char*) next_device->device_serial_no );
if( strlen( (const char*) next_device->device_serial_no ) )
{
snprintf( next_device->device_label,
NWIPE_DEVICE_LABEL_LENGTH,
"%s (%s) - %s S/N:%s",
next_device->device_name,
next_device->device_size_text,
next_device->device_model,
next_device->device_serial_no );
}
else
{
snprintf( next_device->device_label,
NWIPE_DEVICE_LABEL_LENGTH,
"%s (%s) - %s",
next_device->device_name,
next_device->device_size_text,
next_device->device_model );
}
nwipe_log( NWIPE_LOG_NOTICE,
"Found %s, %s, %s, S/N=%s",
next_device->device_name,
next_device->device_model,
next_device->device_size_text,
next_device->device_serial_no );
2020-01-05 16:27:30 -05:00
( *c )[dcount] = next_device;
return 1;
}
/* Remove leading/training whitespace from a string and left justify result */
2020-01-05 16:27:30 -05:00
char* trim( char* str )
{
2020-01-05 16:27:30 -05:00
size_t len = 0;
char* frontp = str;
char* endp = NULL;
if( str == NULL )
{
return NULL;
}
if( str[0] == '\0' )
{
return str;
}
len = strlen( str );
endp = str + len;
/*
* Move the front and back pointers to address the first non-whitespace
* characters from each end.
*/
while( isspace( (unsigned char) *frontp ) )
{
++frontp;
}
if( endp != frontp )
{
while( isspace( (unsigned char) *( --endp ) ) && endp != frontp )
{
}
}
if( str + len - 1 != endp )
*( endp + 1 ) = '\0';
else if( frontp != str && endp == frontp )
*str = '\0';
/*
* Shift the string so that it starts at str so that if it's dynamically
* allocated, we can still free it on the returned pointer. Note the reuse
* of endp to mean the front of the string buffer now.
*/
endp = str;
if( frontp != str )
{
while( *frontp )
{
*endp++ = *frontp++;
}
*endp = '\0';
}
return str;
2013-09-06 23:38:39 +01:00
}