go-deblob.go (2907B)
- // This file is part of https://hacktivis.me/git/go-deblob
- // Copyright © 2019 Haelwenn (lanodan) Monnier <contact+go-deblob-notice@hacktivis.me>
- // SPDX-License-Identifier: BSD-3-Clause
- package main
- import (
- "bytes"
- "fmt"
- "git.sr.ht/~sircmpwn/getopt"
- "io"
- "log"
- "os"
- "path"
- )
- var excludes []string
- var noop bool
- func isBlob(filename string) (result bool) {
- result = false
- // 512 is larger than needed but it's one physical block size
- header := make([]byte, 512)
- file, err := os.Open(filename)
- if err != nil {
- log.Printf("os.Open(%s): %s\n", filename, err)
- return
- }
- defer file.Close()
- _, err = file.Read(header)
- if err != nil && err != io.EOF {
- log.Printf("(%s) os.Read: %s\n", filename, err)
- return
- }
- if bytes.HasPrefix(header, []byte("\x7fELF")) || bytes.HasPrefix(header, []byte("!<arch>\n")) || bytes.HasPrefix(header, []byte("\x55\xAA")) {
- result = true
- }
- return
- }
- func is_excluded(filename string) bool {
- for _, exclude := range excludes {
- matched, err := path.Match(exclude, filename)
- if err != nil {
- log.Printf("path.Match(%s, %s): %s\n", exclude, filename, err)
- return false
- }
- if matched {
- return true
- }
- }
- return false
- }
- func checkDir(dirname string, ignoring bool) {
- dirFd, err := os.Open(dirname)
- if err != nil {
- log.Printf("os.Open(%s): %s\n", dirname, err)
- return
- }
- defer dirFd.Close();
- files, err := dirFd.Readdir(0)
- if err != nil {
- log.Printf("(%s) os.Readdir: %v\n", dirname, err)
- return
- }
- for _, file := range files {
- filename := path.Join(dirname, file.Name())
- if !ignoring {
- ignoring = is_excluded(filename)
- }
- if file.IsDir() {
- checkDir(filename, ignoring)
- } else if isBlob(filename) {
- if ignoring {
- fmt.Printf("ignoring: %s\n", filename)
- continue
- }
- if noop {
- fmt.Printf("detected: %s\n", filename)
- continue
- }
- fmt.Printf("removing: %s\n", filename)
- err = os.Remove(filename)
- if err != nil {
- log.Printf("os.Remove(%s): %s\n", filename, err)
- }
- }
- }
- }
- func usage() {
- println("Usage: go-deblob [-e exclude] [-d workdir]")
- println(" -e Exclude filepath from removal (defaults to none)")
- println(" -d Set working directory (defaults to current dir)")
- println(" -n No actual removal, only scan and log")
- println("See `man 1 go-deblob` for more information.")
- }
- func main() {
- log.SetFlags(log.Lshortfile)
- workdir := "."
- opts, _, err := getopt.Getopts(os.Args, "e:d:n")
- if err != nil {
- log.Fatal(err)
- }
- for _, opt := range opts {
- switch opt.Option {
- case 'e':
- excludes = append(excludes, string(opt.Value))
- case 'd':
- workdir = opt.Value
- case 'n':
- noop = true
- default:
- usage()
- os.Exit(1)
- }
- }
- err = os.Chdir(workdir)
- if err != nil {
- log.Printf("os.Chdir(%s): %s\n", workdir, err)
- os.Exit(1)
- }
- fmt.Println(":: Checking for blobs")
- checkDir(".", false)
- fmt.Println(":: Done checking for blobs")
- }