/*
** Copyright (C) 1998-2022 D&D Corporation. All Rights Reserved
**
** This program is free software; you can redistribute it and/or
** modify it under the same terms as Perl itself.
**
** See <LICENSE> file and <https://dev.perl.org/licenses>
*/
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "CTK.h"
#define PROGRAM_NAME "shred"
#define PROGRAM_VERSION "1.01"
#define AUTHORS "Serz Minus"
#define PASSES 3
#define BUFFSIZE 512
static char *
rnds(int n) {
int pid = getpid();
int i;
static char rndch[BUFFSIZE];
if (pid < 0) pid = pid * -1;
pid += n;
srand(pid % 255);
for (i = 0; i < BUFFSIZE; i++) {
rndch[i] = (rand() % 255);
}
return rndch;
}
static int
pass( int fd, off_t *sizep, int n) {
off_t size = *sizep;
off_t blksize = (off_t) BUFFSIZE;
off_t blks = (off_t) 0;
off_t blkn = (off_t) 0;
off_t blka = size % blksize;
ssize_t ssize; /* Return value from write */
char *buf;
if (blka == 0) {
blks = size / blksize;
} else {
blks = (size - blka) / blksize;
}
if (lseek (fd, (off_t) 0, SEEK_SET) == -1) {
fprintf(stderr, "Error. Can't rewind\n");
fflush (stderr);
return 0;
}
/* Loop to retry partial writes. */
buf = rnds(n);
for (blkn = 0; blkn < blks; blkn ++) {
ssize = write (fd, buf, blksize);
}
if (blka > 0) {
ssize = write (fd, buf, blka);
}
return 1;
}
static int
wipe(char *fn, size_t sz) {
int fd;
off_t size;
size_t i;
unsigned int n;
fd = open (fn, O_WRONLY | O_NOCTTY);
if (fd < 0) {
fprintf(stderr, "Can't open file \"%s\": %s\n", fn, rerr);
fflush (stderr);
return 0;
}
size = sz;
/* printf("SIZE: %d\n",size); */
if (size < 0) {
fprintf(stderr, "File \"%s\" has negative size\n", fn);
fflush (stderr);
return 0;
}
/* Do the work */
n = PASSES;
for (i = 0; i < n; i++) {
if (pass(fd, &size, i)) {
/*printf("Pass %d on %d\n", i+1, n);*/
} else {
/*printf("Fault %d on %d\n", i+1, n);*/
}
}
if (close (fd) != 0) {
fprintf(stderr, "Can't close \"%s\": %s\n", fn, rerr);
fflush (stderr);
return 0;
}
return 1;
}
MODULE = CTK PACKAGE = CTK::UtilXS
SV *
xstest()
ALIAS:
xsver = 1
CODE:
{
RETVAL = newSVpv(PROGRAM_VERSION,0);
}
OUTPUT:
RETVAL
int
wipef(str,sz)
SV * str
size_t sz
PROTOTYPE: $
PREINIT:
char *rstr;
STRLEN rlen;
CODE:
{
int wres;
rstr = SvPV(str, rlen); /* SvPV(sv, len) gives warning for signed len */
/* printf("String: %s\n",rstr); */
wres = wipe(rstr,sz);
RETVAL = wres;
}
OUTPUT:
RETVAL