Add kgz, a gzip tool.

This commit is contained in:
Kyle Isom 2018-09-15 15:08:37 -07:00
parent 160a42ec26
commit 231b98dd68
3 changed files with 207 additions and 0 deletions

View File

@ -25,6 +25,8 @@ Contents:
csrpubdump/ Dump the public key from an X.509 certificate request.
fragment/ Print a fragment of a file.
jlp/ JSON linter/prettifier.
kgz/ Custom gzip compressor / decompressor that handles 99%
of my use cases.
pem2bin/ Dump the binary body of a PEM-encoded block.
pembody/ Print the body of a PEM certificate.
pemit/ Dump data to a PEM file.

23
cmd/kgz/README Normal file
View File

@ -0,0 +1,23 @@
kgz
kgz is like gzip, but supports compressing and decompressing to a different
directory than the source file is in.
Usage: kgz [-l] source [target]
If target is a directory, the basename of the sourcefile will be used
as the target filename. Compression and decompression is selected
based on whether the source filename ends in ".gz".
Flags:
-l level Compression level (0-9). Only meaninful when
compressing a file.

182
cmd/kgz/main.go Normal file
View File

@ -0,0 +1,182 @@
package main
import (
"compress/flate"
"compress/gzip"
"flag"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
)
const gzipExt = ".gz"
func compress(path, target string, level int) error {
sourceFile, err := os.Open(path)
if err != nil {
return errors.Wrap(err, "opening file for read")
}
defer sourceFile.Close()
destFile, err := os.Create(target)
if err != nil {
return errors.Wrap(err, "opening file for write")
}
defer destFile.Close()
gzipCompressor, err := gzip.NewWriterLevel(destFile, level)
if err != nil {
return errors.Wrap(err, "invalid compression level")
}
defer gzipCompressor.Close()
_, err = io.Copy(gzipCompressor, sourceFile)
if err != nil {
return errors.Wrap(err, "compressing file")
}
if err != nil {
return errors.Wrap(err, "stat(2)ing destination file")
}
return nil
}
func uncompress(path, target string) error {
sourceFile, err := os.Open(path)
if err != nil {
return errors.Wrap(err, "opening file for read")
}
defer sourceFile.Close()
gzipUncompressor, err := gzip.NewReader(sourceFile)
if err != nil {
return errors.Wrap(err, "reading gzip headers")
}
defer gzipUncompressor.Close()
destFile, err := os.Create(target)
if err != nil {
return errors.Wrap(err, "opening file for write")
}
defer destFile.Close()
_, err = io.Copy(destFile, gzipUncompressor)
if err != nil {
return errors.Wrap(err, "uncompressing file")
}
return nil
}
func usage(w io.Writer) {
fmt.Fprintf(w, `Usage: %s [-l] source [target]
kgz is like gzip, but supports compressing and decompressing to a different
directory than the source file is in.
Flags:
-l level Compression level (0-9). Only meaninful when
compressing a file.
`, os.Args[0])
}
func init() {
flag.Usage = func() { usage(os.Stderr) }
}
func isDir(path string) bool {
file, err := os.Open(path)
if err == nil {
defer file.Close()
stat, err := file.Stat()
if err != nil {
return false
}
if stat.IsDir() {
return true
}
}
return false
}
func pathForUncompressing(source, dest string) (string, error) {
if !isDir(dest) {
return dest, nil
}
source = filepath.Base(source)
if !strings.HasSuffix(source, gzipExt) {
return "", errors.Errorf("%s is a not gzip-compressed file")
}
outFile := source[:len(source)-len(gzipExt)]
outFile = filepath.Join(dest, outFile)
return outFile, nil
}
func pathForCompressing(source, dest string) (string, error) {
if !isDir(dest) {
return dest, nil
}
source = filepath.Base(source)
if strings.HasSuffix(source, gzipExt) {
return "", errors.Errorf("%s is a gzip-compressed file")
}
dest = filepath.Join(dest, source+gzipExt)
return dest, nil
}
func main() {
var level int
var path string
var target = "."
flag.IntVar(&level, "l", flate.DefaultCompression, "compression level")
flag.Parse()
if flag.NArg() < 1 || flag.NArg() > 2 {
usage(os.Stderr)
os.Exit(1)
}
path = flag.Arg(0)
if flag.NArg() == 2 {
target = flag.Arg(1)
}
if strings.HasSuffix(path, gzipExt) {
target, err := pathForUncompressing(path, target)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
err = uncompress(path, target)
if err != nil {
os.Remove(target)
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
} else {
target, err := pathForCompressing(path, target)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
err = compress(path, target, level)
if err != nil {
os.Remove(target)
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
}
}