2024-07-01 10:23:00 +00:00
# define _SHRED_C
# include <stdio.h>
# include <errno.h>
# include <fcntl.h>
# include <unistd.h>
# include <stdlib.h>
# include <string.h>
# include <sys/mman.h>
# include <sys/stat.h>
# include "config.h"
2024-07-09 12:43:55 +00:00
static char f_flag ;
static char u_flag ;
static char z_flag ;
static int n_loops = 3 ;
2024-07-01 10:23:00 +00:00
2024-07-09 12:43:55 +00:00
static int shred ( int rand_fd , int fd ) {
2024-07-01 10:23:00 +00:00
/* Get size */
off_t size = lseek ( fd , 0 , SEEK_END ) ;
if ( size < = 0 )
return 1 ;
void * buf = mmap ( NULL , size , PROT_WRITE , MAP_SHARED , fd , 0 ) ;
if ( buf = = MAP_FAILED ) {
fprintf ( stderr , " shred: mmap: %s \n " , strerror ( errno ) ) ;
return 1 ;
}
for ( char n = 0 ; n < n_loops ; n + + ) {
if ( read ( rand_fd , buf , size ) = = 0 )
fprintf ( stderr , " shred: %s " , strerror ( errno ) ) ;
fsync ( fd ) ;
}
if ( z_flag )
memset ( buf , 0 , size ) ;
if ( munmap ( buf , size ) ) {
fprintf ( stderr , " shred: munmap: %s \n " , strerror ( errno ) ) ;
return 1 ;
}
return 0 ;
}
int main ( int argc , char * * argv ) {
int opt ;
while ( ( opt = getopt ( argc , argv , " fuzn: " ) ) ! = - 1 ) {
switch ( opt ) {
case ' f ' :
f_flag = 1 ;
break ;
case ' u ' :
u_flag = 1 ;
break ;
case ' z ' :
z_flag = 1 ;
break ;
case ' n ' :
n_loops = atoi ( optarg ) ;
break ;
default :
2024-07-03 14:22:50 +00:00
puts ( " shred [fuzn] [file1 file2...] \n \t -n N Overwrite N times, default 3 \n \t -z Final overwrite with zeros \n \t -u Remove file \n \t -f Chmod to ensure writability " ) ;
2024-07-01 10:23:00 +00:00
return 0 ;
}
}
argv + = optind ;
argc - = optind ;
if ( argc = = 0 ) {
fprintf ( stderr , " shred: missing operand \n " ) ;
return 1 ;
}
int rand_fd = open ( RAND_SOURCE , O_RDONLY ) ;
if ( rand_fd < 0 ) {
fprintf ( stderr , " shred: %s: %s \n " , RAND_SOURCE , strerror ( errno ) ) ;
return 1 ;
}
for ( int i = 0 ; i < argc ; i + + ) {
int fd = open ( argv [ i ] , O_RDWR ) ;
if ( fd < 0 ) {
fprintf ( stderr , " shred: %s is %s \n " , argv [ i ] , strerror ( errno ) ) ;
continue ;
}
shred ( rand_fd , fd ) ;
fsync ( fd ) ;
close ( fd ) ;
if ( f_flag ) {
if ( chmod ( argv [ i ] , 0 ) < 0 )
fprintf ( stderr , " shred: %s is %s \n " , argv [ i ] , strerror ( errno ) ) ;
}
if ( u_flag ) {
if ( unlink ( argv [ i ] ) < 0 )
fprintf ( stderr , " shred: %s is %s \n " , argv [ i ] , strerror ( errno ) ) ;
}
}
close ( rand_fd ) ;
return 0 ;
}