Files
aptly/vendor/github.com/kjk/lzma/lzma_go/main.go
T
2018-06-22 12:44:23 -04:00

262 lines
6.1 KiB
Go

// Copyright (c) 2010, Andrei Vieru. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
//"compress/lzma"
"github.com/kjk/lzma"
"flag"
"fmt"
"io"
"log"
"os"
"path"
"runtime"
"strings"
)
var (
stdout = flag.Bool("c", false, "write on standard output, keep original files unchanged")
decompress = flag.Bool("d", false, "decompress; see also -c and -k")
force = flag.Bool("f", false, "force overwrite of output file")
help = flag.Bool("h", false, "print this help message")
keep = flag.Bool("k", false, "keep original files unchaned")
suffix = flag.String("s", "lzma", "use provided suffix on compressed files")
level = flag.Int("l", 5, "compression level [1 ... 9]")
cores = flag.Int("cores", 1, "number of cores to use for parallelization")
stdin bool
)
func usage() {
fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]... [FILE]\n", os.Args[0])
fmt.Fprintf(os.Stderr, "Compress or uncompress FILE (by default, compress FILE in-place).\n\n")
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\nWith no FILE, or when FILE is -, read standard input.\n")
}
func exit(msg string) {
usage()
fmt.Fprintln(os.Stderr)
log.Fatalf("%s: check args: %s\n\n", os.Args[0], msg)
}
func setByUser(name string) (isSet bool) {
flag.Visit(func(f *flag.Flag) {
if f.Name == name {
isSet = true
}
})
return
}
func main() {
flag.Parse()
if *help == true {
usage()
log.Fatal(0)
}
//if *stdout == true && *suffix != "lzma" {
if *stdout == true && setByUser("s") == true {
exit("stdout set, suffix not used")
}
if *stdout == true && *force == true {
exit("stdout set, force not used")
}
if *stdout == true && *keep == true {
exit("stdout set, keep is redundant")
}
if flag.NArg() > 1 {
exit("too many file, provide at most one file at a time or check order of flags")
}
//if *decompress == true && *level != 5 {
if *decompress == true && setByUser("l") == true {
exit("compression level is used for compression only")
}
if *level < 1 || *level > 9 {
exit("compression level out of range")
}
if *cores < 1 || *cores > 32 {
exit("invalid number of cores")
}
runtime.GOMAXPROCS(*cores)
var inFilePath string
var outFilePath string
if flag.NArg() == 0 || flag.NArg() == 1 && flag.Args()[0] == "-" { // parse args: read from stdin
if *stdout != true {
exit("reading from stdin, can write only to stdout")
}
//if *suffix != "lzma" {
if setByUser("s") == true {
exit("reading from stdin, suffix not needed")
}
stdin = true
} else if flag.NArg() == 1 { // parse args: read from file
inFilePath = flag.Args()[0]
f, err := os.Lstat(inFilePath)
if err != nil {
log.Fatal(err.Error())
}
if f == nil {
exit(fmt.Sprintf("file %s not found", inFilePath))
}
if !!f.IsDir() {
exit(fmt.Sprintf("%s is not a regular file", inFilePath))
}
if *stdout == false { // parse args: write to file
if *suffix == "" {
exit("suffix can't be an empty string")
}
if *decompress == true {
outFileDir, outFileName := path.Split(inFilePath)
if strings.HasSuffix(outFileName, "."+*suffix) {
if len(outFileName) > len("."+*suffix) {
nstr := strings.SplitN(outFileName, ".", len(outFileName))
estr := strings.Join(nstr[0:len(nstr)-1], ".")
outFilePath = outFileDir + estr
} else {
log.Fatalf("error: can't strip suffix .%s from file %s", *suffix, inFilePath)
}
} else {
exit(fmt.Sprintf("file %s doesn't have suffix .%s", inFilePath, *suffix))
}
} else {
outFilePath = inFilePath + "." + *suffix
}
f, err = os.Lstat(outFilePath)
if err != nil && f != nil { // should be: ||| if err != nil && err != "file not found" ||| but i can't find the error's id
log.Fatal(err.Error())
}
if f != nil && !f.IsDir() {
if *force == true {
err = os.Remove(outFilePath)
if err != nil {
log.Fatal(err.Error())
}
} else {
exit(fmt.Sprintf("outFile %s exists. use force to overwrite", outFilePath))
}
} else if f != nil {
exit(fmt.Sprintf("outFile %s exists and is not a regular file", outFilePath))
}
}
}
pr, pw := io.Pipe()
//defer pr.Close()
//defer pw.Close()
if *decompress {
// read from inFile into pw
go func() {
defer pw.Close()
var inFile *os.File
var err error
if stdin == true {
inFile = os.Stdin
} else {
inFile, err = os.Open(inFilePath)
}
defer inFile.Close()
if err != nil {
log.Fatal(err.Error())
}
_, err = io.Copy(pw, inFile)
if err != nil {
log.Fatal(err.Error())
}
}()
// write into outFile from z
defer pr.Close()
z := lzma.NewReader(pr)
defer z.Close()
var outFile *os.File
var err error
if *stdout == true {
outFile = os.Stdout
} else {
outFile, err = os.Create(outFilePath)
}
defer outFile.Close()
if err != nil {
log.Fatal(err.Error())
}
_, err = io.Copy(outFile, z)
if err != nil {
log.Fatal(err.Error())
}
} else {
// read from inFile into z
go func() {
defer pw.Close()
var z io.WriteCloser
var inFile *os.File
var err error
if stdin == true {
inFile = os.Stdin
defer inFile.Close()
z = lzma.NewWriterLevel(pw, *level)
defer z.Close()
} else {
inFile, err = os.Open(inFilePath)
defer inFile.Close()
if err != nil {
log.Fatal(err.Error())
}
f, err := os.Lstat(inFilePath)
if err != nil {
log.Fatal(err.Error())
}
z = lzma.NewWriterSizeLevel(pw, int64(f.Size()), *level)
defer z.Close()
}
_, err = io.Copy(z, inFile)
if err != nil {
log.Fatal(err.Error())
}
}()
// write into outFile from pr
defer pr.Close()
var outFile *os.File
var err error
if *stdout == true {
outFile = os.Stdout
} else {
outFile, err = os.Create(outFilePath)
}
defer outFile.Close()
if err != nil {
log.Fatal(err.Error())
}
_, err = io.Copy(outFile, pr)
if err != nil {
log.Fatal(err.Error())
}
}
if *stdout == false && *keep == false {
err := os.Remove(inFilePath)
if err != nil {
log.Fatal(err.Error())
}
}
}