mirror of
https://codeberg.org/scip/gowipe.git
synced 2025-12-16 04:00:59 +01:00
1st pub version
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
releases
|
||||
a
|
||||
t
|
||||
gowipe
|
||||
89
Makefile
Normal file
89
Makefile
Normal file
@@ -0,0 +1,89 @@
|
||||
# Copyright © 2023 Thomas von Dein
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#
|
||||
# no need to modify anything below
|
||||
tool = gowipe
|
||||
VERSION = $(shell grep VERSION main.go | head -1 | cut -d '"' -f2)
|
||||
archs = darwin freebsd linux windows
|
||||
PREFIX = /usr/local
|
||||
UID = root
|
||||
GID = 0
|
||||
HAVE_POD :=
|
||||
|
||||
all: $(tool) buildlocal
|
||||
|
||||
buildlocal:
|
||||
CGO_LDFLAGS='-static' go build -tags osusergo,netgo -ldflags "-extldflags=-static" -o $(tool)
|
||||
|
||||
install: buildlocal
|
||||
install -d -o $(UID) -g $(GID) $(PREFIX)/bin
|
||||
install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1
|
||||
install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/
|
||||
install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/
|
||||
|
||||
clean:
|
||||
rm -rf $(tool) coverage.out
|
||||
|
||||
test:
|
||||
go test -v ./...
|
||||
|
||||
singletest:
|
||||
@echo "Call like this: ''make singletest TEST=TestPrepareColumns"
|
||||
go test -run $(TEST)
|
||||
|
||||
cover-report:
|
||||
go test ./... -cover -coverprofile=coverage.out
|
||||
go tool cover -html=coverage.out
|
||||
|
||||
goupdate:
|
||||
go get -t -u=patch ./...
|
||||
|
||||
buildall:
|
||||
./mkrel.sh $(tool) $(VERSION)
|
||||
|
||||
release: buildall
|
||||
gh release create v$(VERSION) --generate-notes releases/*
|
||||
|
||||
show-versions: buildlocal
|
||||
@echo "### gowipe version:"
|
||||
@./gowipe -v
|
||||
|
||||
@echo
|
||||
@echo "### go module versions:"
|
||||
@go list -m all
|
||||
|
||||
@echo
|
||||
@echo "### go version used for building:"
|
||||
@grep -m 1 go go.mod
|
||||
|
||||
|
||||
dir:
|
||||
rm -rf a
|
||||
mkdir -p a/b/c
|
||||
date > a/filea
|
||||
date > a/b/fileb
|
||||
date > a/b/c/filec
|
||||
|
||||
bench: all
|
||||
dd if=/dev/zero of=t/fileZ bs=1024 count=200000
|
||||
dd if=/dev/zero of=t/fileM bs=1024 count=200000
|
||||
dd if=/dev/zero of=t/fileS bs=1024 count=200000
|
||||
dd if=/dev/zero of=t/fileE bs=1024 count=200000
|
||||
/usr/bin/time -f "%S" ./gowipe -Z t/fileZ
|
||||
/usr/bin/time -f "%S" ./gowipe -M t/fileM
|
||||
/usr/bin/time -f "%S" ./gowipe -S t/fileS
|
||||
/usr/bin/time -f "%S" ./gowipe -E t/fileE
|
||||
244
crypto.go
Normal file
244
crypto.go
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
Copyright © 2022 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
cryptorand "crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
mathrand "math/rand"
|
||||
"os"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/crypto/argon2"
|
||||
chapo "golang.org/x/crypto/chacha20poly1305"
|
||||
)
|
||||
|
||||
const (
|
||||
SaltSize = 32 // in bytes
|
||||
NonceSize = 24 // in bytes. taken from aead.NonceSize()
|
||||
KeySize = uint32(32) // KeySize is 32 bytes (256 bits).
|
||||
KeyTime = uint32(5)
|
||||
KeyMemory = uint32(1024 * 64) // KeyMemory in KiB. here, 64 MiB.
|
||||
KeyThreads = uint8(4)
|
||||
chunkSize = 1024 * 32 // chunkSize in bytes. here, 32 KiB.
|
||||
|
||||
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-"
|
||||
|
||||
letterIdxBits = 6 // 6 bits to represent a letter index
|
||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
||||
)
|
||||
|
||||
// via https://gist.github.com/dopey/c69559607800d2f2f90b1b1ed4e550fb
|
||||
func AssertAvailablePRNG() {
|
||||
// Assert that a cryptographically secure PRNG is available.
|
||||
// Panic otherwise.
|
||||
buf := make([]byte, 1)
|
||||
|
||||
_, err := io.ReadFull(cryptorand.Reader, buf)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("crypto/rand is unavailable: Read() failed with %#v", err))
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateRandomBytes returns securely generated random bytes.
|
||||
// It will return an error if the system's secure random
|
||||
// number generator fails to function correctly, in which
|
||||
// case the caller should not continue.
|
||||
func GenerateSecureRandomBytes(n int) ([]byte, error) {
|
||||
b := make([]byte, n)
|
||||
_, err := cryptorand.Read(b)
|
||||
// Note that err == nil only if we read len(b) bytes.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// GenerateRandomString returns a securely generated random string.
|
||||
// It will return an error if the system's secure random
|
||||
// number generator fails to function correctly, in which
|
||||
// case the caller should not continue.
|
||||
func GenerateSecureRandomString(n int) (string, error) {
|
||||
ret := make([]byte, n)
|
||||
for i := 0; i < n; i++ {
|
||||
num, err := cryptorand.Int(cryptorand.Reader, big.NewInt(int64(len(letters))))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ret[i] = letters[num.Int64()]
|
||||
}
|
||||
|
||||
return string(ret), nil
|
||||
}
|
||||
|
||||
// via:
|
||||
// https://stackoverflow.com/a/31832326
|
||||
func GenerateMathRandomString(n int) string {
|
||||
b := make([]byte, n)
|
||||
var src = mathrand.NewSource(time.Now().UnixNano())
|
||||
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
|
||||
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
|
||||
if remain == 0 {
|
||||
cache, remain = src.Int63(), letterIdxMax
|
||||
}
|
||||
if idx := int(cache & letterIdxMask); idx < len(letters) {
|
||||
b[i] = letters[idx]
|
||||
i--
|
||||
}
|
||||
cache >>= letterIdxBits
|
||||
remain--
|
||||
}
|
||||
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
func GetRandomKey() ([]byte, error) {
|
||||
password, err := GenerateSecureRandomBytes(int(chapo.KeySize))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
salt, err := GenerateSecureRandomBytes(chapo.NonceSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key := argon2.IDKey(password, salt, KeyTime, KeyMemory, KeyThreads, chapo.KeySize)
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func Encrypt(c *Conf, filename string) error {
|
||||
info, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
size := info.Size()
|
||||
|
||||
outfile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outfile.Close()
|
||||
|
||||
key, err := GetRandomKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
aead, err := chapo.NewX(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < c.count; i++ {
|
||||
for {
|
||||
EncryptChunk(aead, outfile, size)
|
||||
size = size - chunkSize
|
||||
|
||||
if size <= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func EncryptChunk(aead cipher.AEAD, file *os.File, size int64) error {
|
||||
chunk := make([]byte, size)
|
||||
nonce, err := GenerateSecureRandomBytes(int(chapo.NonceSize))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cipher := aead.Seal(nil, nonce, chunk, nil)
|
||||
|
||||
n, err := file.Write(cipher[:size])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if int64(n) != size {
|
||||
return errors.New("invalid number of bytes written")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
func Encrypt(c *Conf, filename string) error {
|
||||
salt, err := GetRand(KeySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
salt1, err := GetRand(KeySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
outfile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outfile.Close()
|
||||
|
||||
key := argon2.IDKey(salt1, salt, KeyTime, KeyMemory, KeyThreads, KeySize)
|
||||
|
||||
aead, err := chacha20poly1305.NewX(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := make([]byte, chunkSize)
|
||||
ad_counter := 0 // associated data is a counter
|
||||
|
||||
for {
|
||||
if n > 0 {
|
||||
// Select a random nonce, and leave capacity for the ciphertext.
|
||||
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+n+aead.Overhead())
|
||||
if m, err := cryptorand.Read(nonce); err != nil || m != aead.NonceSize() {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := buf[:n]
|
||||
// Encrypt the message and append the ciphertext to the nonce.
|
||||
encryptedMsg := aead.Seal(nonce, nonce, msg, []byte(string(ad_counter)))
|
||||
outfile.Write(encryptedMsg)
|
||||
ad_counter += 1
|
||||
}
|
||||
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Println("Error when reading input file chunk :", err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
11
go.mod
Normal file
11
go.mod
Normal file
@@ -0,0 +1,11 @@
|
||||
module gowipe
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/JojiiOfficial/shred v1.2.1 // indirect
|
||||
github.com/lu4p/shred v0.0.0-20201211173428-0347b645d724 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
golang.org/x/crypto v0.15.0 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
)
|
||||
10
go.sum
Normal file
10
go.sum
Normal file
@@ -0,0 +1,10 @@
|
||||
github.com/JojiiOfficial/shred v1.2.1 h1:658CFVTqcAkYVg815vW+guYnyJTLOIoS15tMyPTYhNo=
|
||||
github.com/JojiiOfficial/shred v1.2.1/go.mod h1:/OAxd6eYOhrXb3KW+2wmDog2BiFlUld8oJEKa+xblxU=
|
||||
github.com/lu4p/shred v0.0.0-20201211173428-0347b645d724 h1:nLJRUakdvy2j7JsefrtAUqGRbfJUKKqRu/3BCRA9mIQ=
|
||||
github.com/lu4p/shred v0.0.0-20201211173428-0347b645d724/go.mod h1:6b1kEKx7IPBboPSTnoJZE5sbSDjcNkHHO3Hii8TU8XY=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
238
main.go
Normal file
238
main.go
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
Copyright © 2022 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/JojiiOfficial/shred"
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
const VERSION string = "0.0.2"
|
||||
const Usage string = `This is gowipe - destruct files in a non-recoverable way.
|
||||
|
||||
Usage: gowipe [-rcvz] <file|directory>...
|
||||
|
||||
Options:
|
||||
-r --recursive Delete <dir> recursively
|
||||
-c --count <num> Overwrite files <num> times
|
||||
-m --mode <mode> Use <mode> for overwriting (or use -E, -S, -M, -Z)
|
||||
-n --nodelete Do not delete files after overwriting
|
||||
-N --norename Do not rename the files
|
||||
-v --verbose Verbose output
|
||||
-V --version Show program version
|
||||
-h --help Show usage
|
||||
|
||||
Available modes:
|
||||
zero Overwrite with zeroes (-Z)
|
||||
math Overwrite with math random bytes (-M)
|
||||
secure Overwrite with secure random bytes (default) (-S)
|
||||
encrypt Overwrite with ChaCha2Poly1305 encryption (most secure) (-E)`
|
||||
|
||||
type Conf struct {
|
||||
mode string
|
||||
count int
|
||||
recurse bool
|
||||
nodelete bool
|
||||
norename bool
|
||||
verbose bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
showversion := false
|
||||
showhelp := false
|
||||
optzero := false
|
||||
optsecure := false
|
||||
optmath := false
|
||||
optencrypt := false
|
||||
|
||||
c := Conf{
|
||||
verbose: false,
|
||||
mode: `secure`,
|
||||
count: 30,
|
||||
recurse: false,
|
||||
nodelete: false,
|
||||
norename: false,
|
||||
}
|
||||
|
||||
flag.BoolVarP(&showversion, "version", "V", showversion, "show version")
|
||||
flag.BoolVarP(&showhelp, "help", "h", showversion, "show help")
|
||||
flag.BoolVarP(&c.verbose, "verbose", "v", c.verbose, "verbose")
|
||||
|
||||
flag.StringVarP(&c.mode, "mode", "m", c.mode, "overwrite mode")
|
||||
|
||||
flag.BoolVarP(&optzero, "zero", "Z", optzero, "zero mode")
|
||||
flag.BoolVarP(&optsecure, "secure", "S", optsecure, "secure mode")
|
||||
flag.BoolVarP(&optmath, "math", "M", optmath, "math mode")
|
||||
flag.BoolVarP(&optmath, "encrypt", "E", optmath, "encrypt mode")
|
||||
|
||||
flag.BoolVarP(&c.recurse, "recursive", "r", c.recurse, "recursive")
|
||||
flag.BoolVarP(&c.nodelete, "nodelete", "n", c.nodelete, "don't delete")
|
||||
flag.BoolVarP(&c.norename, "norename", "N", c.norename, "don't rename")
|
||||
flag.IntVarP(&c.count, "count", "c", c.count, "overwrite count")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if showversion {
|
||||
fmt.Printf("This is gowipe version %s\n", VERSION)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if showhelp {
|
||||
fmt.Println(Usage)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if len(flag.Args()) == 0 {
|
||||
fmt.Println(Usage)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
var option shred.WriteOptions
|
||||
|
||||
if optzero {
|
||||
option = shred.WriteZeros
|
||||
}
|
||||
if optmath {
|
||||
option = shred.WriteRand
|
||||
}
|
||||
if optsecure {
|
||||
option = shred.WriteRandSecure
|
||||
}
|
||||
if optencrypt {
|
||||
c.mode = "encrypt"
|
||||
}
|
||||
|
||||
switch c.mode {
|
||||
case `secure`:
|
||||
option = shred.WriteRandSecure
|
||||
case `math`:
|
||||
option = shred.WriteRand
|
||||
case `zero`:
|
||||
option = shred.WriteZeros
|
||||
case `encrypt`:
|
||||
optencrypt = true
|
||||
default:
|
||||
option = shred.WriteRandSecure
|
||||
}
|
||||
|
||||
shredder := shred.Shredder{}
|
||||
shredconf := shred.NewShredderConf(&shredder, option, c.count, !c.nodelete)
|
||||
|
||||
for _, file := range flag.Args() {
|
||||
Wipe(file, &c, shredconf)
|
||||
}
|
||||
}
|
||||
|
||||
func Wipe(file string, c *Conf, wiper *shred.ShredderConf) {
|
||||
if info, err := os.Stat(file); err == nil {
|
||||
|
||||
if info.IsDir() {
|
||||
if !c.recurse {
|
||||
fmt.Printf("-r not set, ignoring directory %s\n", file)
|
||||
return
|
||||
}
|
||||
|
||||
files, err := ioutil.ReadDir(file)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, entry := range files {
|
||||
Wipe(filepath.Join(file, entry.Name()), c, wiper)
|
||||
}
|
||||
|
||||
if !c.nodelete {
|
||||
err = os.Remove(Rename(file, c))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if c.mode == "encrypt" {
|
||||
err := Encrypt(c, file)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
Rename(file, c)
|
||||
} else {
|
||||
wiper.ShredFile(Rename(file, c))
|
||||
}
|
||||
}
|
||||
|
||||
if c.verbose {
|
||||
fmt.Printf("Wiped %d times: %s\n", c.count, file)
|
||||
}
|
||||
} else {
|
||||
if os.IsNotExist(err) {
|
||||
fmt.Printf("No such file or directory: %s\n", file)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func Rename(file string, c *Conf) string {
|
||||
var newname string
|
||||
dir := filepath.Dir(file)
|
||||
base := filepath.Base(file)
|
||||
length := len(base)
|
||||
|
||||
for i := 0; i < c.count; i++ {
|
||||
for {
|
||||
switch c.mode {
|
||||
case `secure`:
|
||||
new, err := GenerateSecureRandomString(length)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
newname = new
|
||||
case `math`:
|
||||
newname = GenerateMathRandomString(length)
|
||||
case `zero`:
|
||||
newname = strings.Repeat("0", length)
|
||||
}
|
||||
if newname != base {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if c.verbose {
|
||||
fmt.Printf("renaming %s/%s => %s/%s\n", dir, base, dir, newname)
|
||||
}
|
||||
*/
|
||||
|
||||
err := os.Rename(filepath.Join(dir, base), filepath.Join(dir, newname))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
base = newname
|
||||
}
|
||||
|
||||
return filepath.Join(dir, newname)
|
||||
}
|
||||
65
mkrel.sh
Executable file
65
mkrel.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright © 2022 Thomas von Dein
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# get list with: go tool dist list
|
||||
DIST="darwin/amd64
|
||||
freebsd/amd64
|
||||
linux/amd64
|
||||
netbsd/amd64
|
||||
openbsd/amd64
|
||||
windows/amd64"
|
||||
|
||||
tool="$1"
|
||||
version="$2"
|
||||
|
||||
if test -z "$version"; then
|
||||
echo "Usage: $0 <tool name> <release version>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf releases
|
||||
mkdir -p releases
|
||||
|
||||
|
||||
for D in $DIST; do
|
||||
os=${D/\/*/}
|
||||
arch=${D/*\//}
|
||||
binfile="releases/${tool}-${os}-${arch}-${version}"
|
||||
tardir="${tool}-${os}-${arch}-${version}"
|
||||
tarfile="releases/${tool}-${os}-${arch}-${version}.tar.gz"
|
||||
set -x
|
||||
GOOS=${os} GOARCH=${arch} go build -o ${binfile} -ldflags "-X 'github.com/tlinden/tablizer/cfg.VERSION=${version}'"
|
||||
mkdir -p ${tardir}
|
||||
cp ${binfile} README.md LICENSE ${tardir}/
|
||||
echo 'tool = tablizer
|
||||
PREFIX = /usr/local
|
||||
UID = root
|
||||
GID = 0
|
||||
|
||||
install:
|
||||
install -d -o $(UID) -g $(GID) $(PREFIX)/bin
|
||||
install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1
|
||||
install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/
|
||||
install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/' > ${tardir}/Makefile
|
||||
tar cpzf ${tarfile} ${tardir}
|
||||
sha256sum ${binfile} | cut -d' ' -f1 > ${binfile}.sha256
|
||||
sha256sum ${tarfile} | cut -d' ' -f1 > ${tarfile}.sha256
|
||||
rm -rf ${tardir}
|
||||
set +x
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user