github.com/StackExchange/blackbox/v2@v2.0.1-0.20220331193400-d84e904973ab/pkg/bbutil/shred.go (about) 1 package bbutil 2 3 // Pick an appropriate secure erase command for this operating system 4 // or just delete the file with os.Remove(). 5 6 // Code rewritten based https://codereview.stackexchange.com/questions/245072 7 8 import ( 9 "fmt" 10 "io/ioutil" 11 "os" 12 "os/exec" 13 ) 14 15 var shredCmds = []struct { 16 name, opts string 17 }{ 18 {"sdelete", "-a"}, 19 {"shred", "-u"}, 20 {"srm", "-f"}, 21 {"rm", "-Pf"}, 22 } 23 24 func shredTemp(path, opts string) error { 25 file, err := ioutil.TempFile("", "shredTemp.") 26 if err != nil { 27 return err 28 } 29 filename := file.Name() 30 defer os.Remove(filename) 31 defer file.Close() 32 33 err = file.Close() 34 if err != nil { 35 return err 36 } 37 err = RunBash(path, opts, filename) 38 if err != nil { 39 return err 40 } 41 return nil 42 } 43 44 var shredPath, shredOpts = func() (string, string) { 45 for _, cmd := range shredCmds { 46 path, err := exec.LookPath(cmd.name) 47 if err != nil { 48 continue 49 } 50 err = shredTemp(path, cmd.opts) 51 if err == nil { 52 return path, cmd.opts 53 } 54 } 55 return "", "" 56 }() 57 58 // ShredInfo reveals the shred command and flags (for "blackbox info") 59 func ShredInfo() string { 60 return shredPath + " " + shredOpts 61 } 62 63 // shredFile shreds one file. 64 func shredFile(filename string) error { 65 fi, err := os.Stat(filename) 66 if err != nil { 67 return err 68 } 69 if !fi.Mode().IsRegular() { 70 err := fmt.Errorf("filename is not mode regular") 71 return err 72 } 73 74 if shredPath == "" { 75 // No secure erase command found. Default to a normal file delete. 76 // TODO(tlim): Print a warning? Have a flag that causes this to be an error? 77 return os.Remove(filename) 78 } 79 80 err = RunBash(shredPath, shredOpts, filename) 81 if err != nil { 82 return err 83 } 84 return nil 85 } 86 87 // ShredFiles securely erases a list of files. 88 func ShredFiles(names []string) error { 89 90 // TODO(tlim) DO the shredding in parallel like in v1. 91 92 var eerr error 93 for _, n := range names { 94 _, err := os.Stat(n) 95 if err != nil { 96 if os.IsNotExist(err) { 97 fmt.Printf("======= already gone: %q\n", n) 98 continue 99 } 100 } 101 fmt.Printf("========== SHREDDING: %q\n", n) 102 e := shredFile(n) 103 if e != nil { 104 eerr = e 105 fmt.Printf("ERROR: %v\n", e) 106 } 107 } 108 return eerr 109 }