xref: /aosp_15_r20/external/toybox/toys/other/shred.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* shred.c - Overwrite a file to securely delete
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2014 Rob Landley <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  *
5*cf5a6c84SAndroid Build Coastguard Worker  * No standard
6*cf5a6c84SAndroid Build Coastguard Worker 
7*cf5a6c84SAndroid Build Coastguard Worker USE_SHRED(NEWTOY(shred, "<1zxus#<1n#<1o#<0f", TOYFLAG_USR|TOYFLAG_BIN))
8*cf5a6c84SAndroid Build Coastguard Worker 
9*cf5a6c84SAndroid Build Coastguard Worker config SHRED
10*cf5a6c84SAndroid Build Coastguard Worker   bool "shred"
11*cf5a6c84SAndroid Build Coastguard Worker   default y
12*cf5a6c84SAndroid Build Coastguard Worker   help
13*cf5a6c84SAndroid Build Coastguard Worker     usage: shred [-fuxz] [-n COUNT] [-o OFFSET] [-s SIZE] FILE...
14*cf5a6c84SAndroid Build Coastguard Worker 
15*cf5a6c84SAndroid Build Coastguard Worker     Securely delete a file by overwriting its contents with random data.
16*cf5a6c84SAndroid Build Coastguard Worker 
17*cf5a6c84SAndroid Build Coastguard Worker     -f		Force (chmod if necessary)
18*cf5a6c84SAndroid Build Coastguard Worker     -n COUNT	Random overwrite iterations (default 1)
19*cf5a6c84SAndroid Build Coastguard Worker     -o OFFSET	Start at OFFSET
20*cf5a6c84SAndroid Build Coastguard Worker     -s SIZE		Use SIZE instead of detecting file size
21*cf5a6c84SAndroid Build Coastguard Worker     -u		Unlink (actually delete file when done)
22*cf5a6c84SAndroid Build Coastguard Worker     -x		Use exact size (default without -s rounds up to next 4k)
23*cf5a6c84SAndroid Build Coastguard Worker     -z		Zero at end
24*cf5a6c84SAndroid Build Coastguard Worker 
25*cf5a6c84SAndroid Build Coastguard Worker     Note: data journaling filesystems render this command useless, you must
26*cf5a6c84SAndroid Build Coastguard Worker     overwrite all free space (fill up disk) to erase old data on those.
27*cf5a6c84SAndroid Build Coastguard Worker */
28*cf5a6c84SAndroid Build Coastguard Worker 
29*cf5a6c84SAndroid Build Coastguard Worker #define FOR_shred
30*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
31*cf5a6c84SAndroid Build Coastguard Worker 
GLOBALS(long o,n,s;)32*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
33*cf5a6c84SAndroid Build Coastguard Worker   long o, n, s;
34*cf5a6c84SAndroid Build Coastguard Worker )
35*cf5a6c84SAndroid Build Coastguard Worker 
36*cf5a6c84SAndroid Build Coastguard Worker void shred_main(void)
37*cf5a6c84SAndroid Build Coastguard Worker {
38*cf5a6c84SAndroid Build Coastguard Worker   char **try;
39*cf5a6c84SAndroid Build Coastguard Worker 
40*cf5a6c84SAndroid Build Coastguard Worker   if (!FLAG(n)) TT.n++;
41*cf5a6c84SAndroid Build Coastguard Worker 
42*cf5a6c84SAndroid Build Coastguard Worker   // We don't use loopfiles() here because "-" isn't stdin, and want to
43*cf5a6c84SAndroid Build Coastguard Worker   // respond to files we can't open via chmod.
44*cf5a6c84SAndroid Build Coastguard Worker 
45*cf5a6c84SAndroid Build Coastguard Worker   for (try = toys.optargs; *try; try++) {
46*cf5a6c84SAndroid Build Coastguard Worker     off_t pos = 0, len = TT.s;
47*cf5a6c84SAndroid Build Coastguard Worker     int fd = open(*try, O_RDWR), iter = 0, throw;
48*cf5a6c84SAndroid Build Coastguard Worker 
49*cf5a6c84SAndroid Build Coastguard Worker     // do -f chmod if necessary
50*cf5a6c84SAndroid Build Coastguard Worker     if (fd == -1 && FLAG(f)) {
51*cf5a6c84SAndroid Build Coastguard Worker       chmod(*try, 0600);
52*cf5a6c84SAndroid Build Coastguard Worker       fd = open(*try, O_RDWR);
53*cf5a6c84SAndroid Build Coastguard Worker     }
54*cf5a6c84SAndroid Build Coastguard Worker     if (fd == -1) {
55*cf5a6c84SAndroid Build Coastguard Worker       perror_msg_raw(*try);
56*cf5a6c84SAndroid Build Coastguard Worker       continue;
57*cf5a6c84SAndroid Build Coastguard Worker     }
58*cf5a6c84SAndroid Build Coastguard Worker 
59*cf5a6c84SAndroid Build Coastguard Worker     // determine length
60*cf5a6c84SAndroid Build Coastguard Worker     if (!len) len = fdlength(fd);
61*cf5a6c84SAndroid Build Coastguard Worker     if (len<1) {
62*cf5a6c84SAndroid Build Coastguard Worker       error_msg("%s: needs -s", *try);
63*cf5a6c84SAndroid Build Coastguard Worker       close(fd);
64*cf5a6c84SAndroid Build Coastguard Worker       continue;
65*cf5a6c84SAndroid Build Coastguard Worker     }
66*cf5a6c84SAndroid Build Coastguard Worker 
67*cf5a6c84SAndroid Build Coastguard Worker     // Loop through, writing to this file
68*cf5a6c84SAndroid Build Coastguard Worker     for (;;) {
69*cf5a6c84SAndroid Build Coastguard Worker       // Advance to next -n or -z?
70*cf5a6c84SAndroid Build Coastguard Worker 
71*cf5a6c84SAndroid Build Coastguard Worker       if (pos >= len) {
72*cf5a6c84SAndroid Build Coastguard Worker         pos = -1;
73*cf5a6c84SAndroid Build Coastguard Worker         if (++iter == TT.n && FLAG(z)) {
74*cf5a6c84SAndroid Build Coastguard Worker           memset(toybuf, 0, sizeof(toybuf));
75*cf5a6c84SAndroid Build Coastguard Worker           continue;
76*cf5a6c84SAndroid Build Coastguard Worker         }
77*cf5a6c84SAndroid Build Coastguard Worker         if (iter >= TT.n) break;
78*cf5a6c84SAndroid Build Coastguard Worker       }
79*cf5a6c84SAndroid Build Coastguard Worker 
80*cf5a6c84SAndroid Build Coastguard Worker       if (pos < TT.o) {
81*cf5a6c84SAndroid Build Coastguard Worker         if (TT.o != lseek(fd, TT.o, SEEK_SET)) {
82*cf5a6c84SAndroid Build Coastguard Worker           perror_msg_raw(*try);
83*cf5a6c84SAndroid Build Coastguard Worker           break;
84*cf5a6c84SAndroid Build Coastguard Worker         }
85*cf5a6c84SAndroid Build Coastguard Worker         pos = TT.o;
86*cf5a6c84SAndroid Build Coastguard Worker       }
87*cf5a6c84SAndroid Build Coastguard Worker 
88*cf5a6c84SAndroid Build Coastguard Worker       // Determine length, read random data if not zeroing, write.
89*cf5a6c84SAndroid Build Coastguard Worker 
90*cf5a6c84SAndroid Build Coastguard Worker       throw = sizeof(toybuf);
91*cf5a6c84SAndroid Build Coastguard Worker       if (FLAG(x) && len-pos < throw) throw = len-pos;
92*cf5a6c84SAndroid Build Coastguard Worker 
93*cf5a6c84SAndroid Build Coastguard Worker       if (iter != TT.n) xgetrandom(toybuf, throw);
94*cf5a6c84SAndroid Build Coastguard Worker       if (throw != writeall(fd, toybuf, throw)) perror_msg_raw(*try);
95*cf5a6c84SAndroid Build Coastguard Worker       pos += throw;
96*cf5a6c84SAndroid Build Coastguard Worker     }
97*cf5a6c84SAndroid Build Coastguard Worker     if (FLAG(u) && unlink(*try)) perror_msg("unlink '%s'", *try);
98*cf5a6c84SAndroid Build Coastguard Worker   }
99*cf5a6c84SAndroid Build Coastguard Worker }
100