Table of Contents

About

qtip is a small program that performs a 4-pass overwrite of a file before deleting it.

You can compile the program with 'gcc', for example, by running:

gcc -o qtip qtip.c

Implementations for Other Systems

Code

qtip.c
/*************************************************************************/
/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
/*                                                                       */
/*  qtip                                                                 */
/*                                                                       */
/*  Quick and secure erasure of files: random pass, even pass (0xAA),     */
/*  odd pass (0x55), random pass.                                        */
/*                                                                       */
/*  Amiga: Compile using SASC: sc link qtip.c                            */
/*                                                                       */
/*************************************************************************/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
 
#define EVEN 0xAA
#define ODD 0x55
 
int main(int argc, char **argv) {
    FILE *fp;
    struct stat sta, stb;
    time_t t;
    long long size;
    int rnd;
 
    /* Check syntax first. */
    if(argc != 2) {
        printf("Syntax: qtip <FILE>\n");
        return 1;
    }
 
    /* Determine whether the file exists. */
    if(stat(argv[1], &sta) != 0) {
        printf("Unable to find file: %s\n", argv[1]);
        return 1;
    }
 
    /* If file is empty, remove the file. */
    if(sta.st_size == 0) {
        /* Check that the file is still there. */
        if(stat(argv[1], &stb) != 0) {
            printf("Unable to find file: %s\n", argv[1]);
            return 1;
        }
        /* Check that the inode is still the same. */
        if(sta.st_ino != stb.st_ino) {
            printf("File inode has changed. Aborting remove.\n");
            return 1;
        }
        /* Delete the file. */
        if(remove(argv[1]) != 0) {
            printf("Unable to remove file.\n");
            return 1;
        }
        return 0;
    }
 
    /* Open in binary read-write mode. */
    if ((fp = fopen(argv[1], "rb+")) == NULL) {
        printf("Unable to open file: %s\n", argv[1]);
        return 1;
    }
 
    /* Random pass. */
    srand((unsigned) time(&t));
    size = sta.st_size;
    do {
        rnd = rand() % 256;
        if(fputc(rnd,fp) != rnd) {
            printf("Failed to write random pass.");
            return 1;
        }
    }
    while(--size);
 
    /* Rewind. */
    rewind(fp);
 
    /* Even pass: EVEN. */
    size = sta.st_size;
    do {
        if(fputc(EVEN, fp) != EVEN) {
            printf("Failed to write even pass.");
            return 1;
        }
    }
    while(--size);
 
    /* Rewind. */
    rewind(fp);
 
    /* Odd pass: ODD. */
    size = sta.st_size;
    do {
        if(fputc(ODD, fp) != ODD) {
            printf("Failed to write odd pass.");
            return 1;
        }
    }
    while(--size);
 
    /* Rewind. */
    rewind(fp);
 
    /* Random pass. */
    srand((unsigned) time(&t));
    size = sta.st_size;
    do {
        rnd = rand() % 256;
        if(fputc(rnd,fp) != rnd) {
            printf("Failed to write random pass.");
            return 1;
        }
    }
    while(--size);
 
    /* Close file handle. */
    fclose(fp);
 
    /* Check that the file is still there. */
    if(stat(argv[1], &stb) != 0) {
        printf("Unable to find file: %s\n", argv[1]);
        return 1;
    }
 
    /* Check that the inode is still the same. */
    if(sta.st_ino != stb.st_ino) {
        printf("File inode has changed. Aborting remove.\n");
        return 1;
    }
 
    /* Now delete the file. */
    if(remove(argv[1]) != 0) {
        printf("Unable to remove file.\n");
        return 1;
    }
 
    return 0;
}