Skip to content

Instantly share code, notes, and snippets.

@magical
Created July 6, 2020 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save magical/d229ad2987137223a241c5cacd2fca3c to your computer and use it in GitHub Desktop.
Save magical/d229ad2987137223a241c5cacd2fca3c to your computer and use it in GitHub Desktop.
// Usage: extractgarc garcfile outdir
// Extract and decompress all files in garcfile to outdir.
package main
import (
"fmt"
"io"
"log"
"os"
"path/filepath"
"github.com/magical/gen7/garc"
"github.com/magical/gen7/lz"
)
func main() {
filename := os.Args[1]
outdir := os.Args[2]
if filename == "" || outdir == "" {
return
}
f, err := os.Open(filename)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
gfiles, err := garc.Files(f)
if err != nil {
fmt.Println(err)
return
}
for _, file := range gfiles {
var r io.Reader
z, err := lz.NewReader(file)
if err != nil {
r = file
//log.Println(err)
//continue
} else {
r = z
}
outname := fmt.Sprintf("%d.%d", file.Major, file.Minor)
out, err := os.Create(filepath.Join(outdir, outname))
if err != nil {
log.Printf("%s[%s]: %s", filename, outname, err)
break
}
_, err = io.Copy(out, r)
if err != nil {
log.Printf("%s[%s]: %s", filename, outname, err)
}
}
}
package main
import (
"bytes"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"github.com/magical/gen7/garc"
"github.com/magical/gen7/lz"
)
var length int
var decompress bool
func main() {
flag.IntVar(&length, "w", 10, "length of hex dump, in words")
flag.BoolVar(&decompress, "z", false, "attempt to decompress")
flag.Parse()
if flag.NArg() < 1 {
flag.Usage()
return
}
filename := flag.Arg(0)
err := view(filename)
if err != nil {
fmt.Println(err)
}
}
func view(filename string) error {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
files, err := garc.Files(f)
if err != nil {
return err
}
for i, file := range files {
num := fmt.Sprintf("(%d.%d)", file.Major, file.Minor)
var dfile readerSize = file
var fsize = file.Size()
compressed := false
if decompress {
dfile, compressed = tryDecompress(file)
if compressed {
fsize = dfile.Size()
fmt.Print("*")
} else {
fmt.Print(" ")
}
}
fmt.Printf("%08x [%8x] %5d %8s: ", file.Offset(), fsize, i, num)
var nn, n int64
nn, err := hex(dfile, length)
if err == nil && compressed && false {
// Make sure there are no decoding errors
n, err = io.Copy(ioutil.Discard, dfile)
nn += n
if nn != dfile.Size() {
fmt.Printf("size mismatch: %d expected %d\n", nn, dfile.Size())
}
}
if err != nil {
fmt.Println(err)
}
}
return nil
}
type readerSize interface {
io.Reader
Size() int64
}
func tryDecompress(r *garc.File) (readerSize, bool) {
z, err := lz.NewReader(r)
if err != nil || z.Size() < r.Size() {
r.Seek(0, 0)
return r, false
}
return z, true
}
func hex(r io.Reader, length int) (nn int64, err error) {
const hex = "0123456789ABCDEF"
var b [4]byte
var buf bytes.Buffer
for {
n, err := r.Read(b[:])
nn += int64(n)
for i := 0; i < n; i++ {
buf.WriteByte(hex[b[i]>>4])
buf.WriteByte(hex[b[i]&0xF])
}
if buf.Len() >= length*9-1 {
buf.WriteString("...")
break
}
if err == io.EOF {
break
}
if err != nil {
return nn, err
}
buf.WriteByte(' ')
}
buf.WriteByte('\n')
io.Copy(os.Stdout, &buf)
return nn, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment