10f66f451Sopenharmony_ci/* shred.c - Overwrite a file to securely delete 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2014 Rob Landley <rob@landley.net> 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * No standard 60f66f451Sopenharmony_ci 70f66f451Sopenharmony_ciUSE_SHRED(NEWTOY(shred, "<1zxus#<1n#<1o#<0f", TOYFLAG_USR|TOYFLAG_BIN)) 80f66f451Sopenharmony_ci 90f66f451Sopenharmony_ciconfig SHRED 100f66f451Sopenharmony_ci bool "shred" 110f66f451Sopenharmony_ci default y 120f66f451Sopenharmony_ci help 130f66f451Sopenharmony_ci usage: shred [-fuxz] [-n COUNT] [-o OFFSET] [-s SIZE] FILE... 140f66f451Sopenharmony_ci 150f66f451Sopenharmony_ci Securely delete a file by overwriting its contents with random data. 160f66f451Sopenharmony_ci 170f66f451Sopenharmony_ci -f Force (chmod if necessary) 180f66f451Sopenharmony_ci -n COUNT Random overwrite iterations (default 1) 190f66f451Sopenharmony_ci -o OFFSET Start at OFFSET 200f66f451Sopenharmony_ci -s SIZE Use SIZE instead of detecting file size 210f66f451Sopenharmony_ci -u Unlink (actually delete file when done) 220f66f451Sopenharmony_ci -x Use exact size (default without -s rounds up to next 4k) 230f66f451Sopenharmony_ci -z Zero at end 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_ci Note: data journaling filesystems render this command useless, you must 260f66f451Sopenharmony_ci overwrite all free space (fill up disk) to erase old data on those. 270f66f451Sopenharmony_ci*/ 280f66f451Sopenharmony_ci 290f66f451Sopenharmony_ci#define FOR_shred 300f66f451Sopenharmony_ci#include "toys.h" 310f66f451Sopenharmony_ci 320f66f451Sopenharmony_ciGLOBALS( 330f66f451Sopenharmony_ci long o, n, s; 340f66f451Sopenharmony_ci) 350f66f451Sopenharmony_ci 360f66f451Sopenharmony_civoid shred_main(void) 370f66f451Sopenharmony_ci{ 380f66f451Sopenharmony_ci char **try; 390f66f451Sopenharmony_ci 400f66f451Sopenharmony_ci if (!FLAG(n)) TT.n++; 410f66f451Sopenharmony_ci 420f66f451Sopenharmony_ci // We don't use loopfiles() here because "-" isn't stdin, and want to 430f66f451Sopenharmony_ci // respond to files we can't open via chmod. 440f66f451Sopenharmony_ci 450f66f451Sopenharmony_ci for (try = toys.optargs; *try; try++) { 460f66f451Sopenharmony_ci off_t pos = 0, len = TT.s; 470f66f451Sopenharmony_ci int fd = open(*try, O_RDWR), iter = 0, throw; 480f66f451Sopenharmony_ci 490f66f451Sopenharmony_ci // do -f chmod if necessary 500f66f451Sopenharmony_ci if (fd == -1 && FLAG(f)) { 510f66f451Sopenharmony_ci chmod(*try, 0600); 520f66f451Sopenharmony_ci fd = open(*try, O_RDWR); 530f66f451Sopenharmony_ci } 540f66f451Sopenharmony_ci if (fd == -1) { 550f66f451Sopenharmony_ci perror_msg_raw(*try); 560f66f451Sopenharmony_ci continue; 570f66f451Sopenharmony_ci } 580f66f451Sopenharmony_ci 590f66f451Sopenharmony_ci // determine length 600f66f451Sopenharmony_ci if (!len) len = fdlength(fd); 610f66f451Sopenharmony_ci if (len<1) { 620f66f451Sopenharmony_ci error_msg("%s: needs -s", *try); 630f66f451Sopenharmony_ci close(fd); 640f66f451Sopenharmony_ci continue; 650f66f451Sopenharmony_ci } 660f66f451Sopenharmony_ci 670f66f451Sopenharmony_ci // Loop through, writing to this file 680f66f451Sopenharmony_ci for (;;) { 690f66f451Sopenharmony_ci // Advance to next -n or -z? 700f66f451Sopenharmony_ci 710f66f451Sopenharmony_ci if (pos >= len) { 720f66f451Sopenharmony_ci pos = -1; 730f66f451Sopenharmony_ci if (++iter == TT.n && FLAG(z)) { 740f66f451Sopenharmony_ci memset(toybuf, 0, sizeof(toybuf)); 750f66f451Sopenharmony_ci continue; 760f66f451Sopenharmony_ci } 770f66f451Sopenharmony_ci if (iter >= TT.n) break; 780f66f451Sopenharmony_ci } 790f66f451Sopenharmony_ci 800f66f451Sopenharmony_ci if (pos < TT.o) { 810f66f451Sopenharmony_ci if (TT.o != lseek(fd, TT.o, SEEK_SET)) { 820f66f451Sopenharmony_ci perror_msg_raw(*try); 830f66f451Sopenharmony_ci break; 840f66f451Sopenharmony_ci } 850f66f451Sopenharmony_ci pos = TT.o; 860f66f451Sopenharmony_ci } 870f66f451Sopenharmony_ci 880f66f451Sopenharmony_ci // Determine length, read random data if not zeroing, write. 890f66f451Sopenharmony_ci 900f66f451Sopenharmony_ci throw = sizeof(toybuf); 910f66f451Sopenharmony_ci if (FLAG(x) && len-pos < throw) throw = len-pos; 920f66f451Sopenharmony_ci 930f66f451Sopenharmony_ci if (iter != TT.n) xgetrandom(toybuf, throw, 0); 940f66f451Sopenharmony_ci if (throw != writeall(fd, toybuf, throw)) perror_msg_raw(*try); 950f66f451Sopenharmony_ci pos += throw; 960f66f451Sopenharmony_ci } 970f66f451Sopenharmony_ci if (FLAG(u) && unlink(*try)) perror_msg("unlink '%s'", *try); 980f66f451Sopenharmony_ci } 990f66f451Sopenharmony_ci} 100