// Copyright 2014 The Go Authors. 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 (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

/*
The archive format is:

First, on a line by itself
	!<arch>

Then zero or more file records. Each file record has a fixed-size one-line header
followed by data bytes followed by an optional padding byte. The header is:

	%-16s%-12d%-6d%-6d%-8o%-10d`
	name mtime uid gid mode size

(note the trailing backquote). The %-16s here means at most 16 *bytes* of
the name, and if shorter, space padded on the right.
*/

const usageMessage = `Usage: pack op file.a [name....]
Where op is one of cprtx optionally followed by v for verbose output.
For compatibility with old Go build environments the op string grc is
accepted as a synonym for c.

For more information, run
	godoc cmd/pack`

func usage() {
	fmt.Fprintln(os.Stderr, usageMessage)
	os.Exit(2)
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("pack: ")
	// need "pack op archive" at least.
	if len(os.Args) < 3 {
		log.Print("not enough arguments")
		fmt.Fprintln(os.Stderr)
		usage()
	}
	setOp(os.Args[1])
	var ar *Archive
	switch op {
	case 'p':
		ar = archive(os.Args[2], os.O_RDONLY, os.Args[3:])
		ar.scan(ar.printContents)
	case 'r':
		ar = archive(os.Args[2], os.O_RDWR, os.Args[3:])
		ar.scan(ar.skipContents)
		ar.addFiles()
	case 'c':
		ar = archive(os.Args[2], os.O_RDWR|os.O_TRUNC, os.Args[3:])
		ar.addPkgdef()
		ar.addFiles()
	case 't':
		ar = archive(os.Args[2], os.O_RDONLY, os.Args[3:])
		ar.scan(ar.tableOfContents)
	case 'x':
		ar = archive(os.Args[2], os.O_RDONLY, os.Args[3:])
		ar.scan(ar.extractContents)
	default:
		log.Printf("invalid operation %q", os.Args[1])
		fmt.Fprintln(os.Stderr)
		usage()
	}
	if len(ar.files) > 0 {
		log.Fatalf("file %q not in archive", ar.files[0])
	}
}

// The unusual ancestry means the arguments are not Go-standard.
// These variables hold the decoded operation specified by the first argument.
// op holds the operation we are doing (prtx).
// verbose tells whether the 'v' option was specified.
var (
	op      rune
	verbose bool
)

// setOp parses the operation string (first argument).
func setOp(arg string) {
	// Recognize 'go tool pack grc' because that was the
	// formerly canonical way to build a new archive
	// from a set of input files. Accepting it keeps old
	// build systems working with both Go 1.2 and Go 1.3.
	if arg == "grc" {
		arg = "c"
	}

	for _, r := range arg {
		switch r {
		case 'c', 'p', 'r', 't', 'x':
			if op != 0 {
				// At most one can be set.
				usage()
			}
			op = r
		case 'v':
			if verbose {
				// Can be set only once.
				usage()
			}
			verbose = true
		default:
			usage()
		}
	}
}

const (
	arHeader    = "!<arch>\n"
	entryHeader = "%s%-12d%-6d%-6d%-8o%-10d`\n"
	// In entryHeader the first entry, the name, is always printed as 16 bytes right-padded.
	entryLen   = 16 + 12 + 6 + 6 + 8 + 10 + 1 + 1
	timeFormat = "Jan _2 15:04 2006"
)

// An Archive represents an open archive file. It is always scanned sequentially
// from start to end, without backing up.
type Archive struct {
	fd       *os.File // Open file descriptor.
	files    []string // Explicit list of files to be processed.
	pad      int      // Padding bytes required at end of current archive file
	matchAll bool     // match all files in archive
}

// archive opens (and if necessary creates) the named archive.
func archive(name string, mode int, files []string) *Archive {
	// If the file exists, it must be an archive. If it doesn't exist, or if
	// we're doing the c command, indicated by O_TRUNC, truncate the archive.
	if !existingArchive(name) || mode&os.O_TRUNC != 0 {
		create(name)
		mode &^= os.O_TRUNC
	}
	fd, err := os.OpenFile(name, mode, 0)
	if err != nil {
		log.Fatal(err)
	}
	checkHeader(fd)
	return &Archive{
		fd:       fd,
		files:    files,
		matchAll: len(files) == 0,
	}
}

// create creates and initializes an archive that does not exist.
func create(name string) {
	fd, err := os.Create(name)
	if err != nil {
		log.Fatal(err)
	}
	_, err = fmt.Fprint(fd, arHeader)
	if err != nil {
		log.Fatal(err)
	}
	fd.Close()
}

// existingArchive reports whether the file exists and is a valid archive.
// If it exists but is not an archive, existingArchive will exit.
func existingArchive(name string) bool {
	fd, err := os.Open(name)
	if err != nil {
		if os.IsNotExist(err) {
			return false
		}
		log.Fatal("cannot open file: %s", err)
	}
	checkHeader(fd)
	fd.Close()
	return true
}

// checkHeader verifies the header of the file. It assumes the file
// is positioned at 0 and leaves it positioned at the end of the header.
func checkHeader(fd *os.File) {
	buf := make([]byte, len(arHeader))
	_, err := io.ReadFull(fd, buf)
	if err != nil || string(buf) != arHeader {
		log.Fatal("%s is not an archive: bad header", fd.Name())
	}
}

// An Entry is the internal representation of the per-file header information of one entry in the archive.
type Entry struct {
	name  string
	mtime int64
	uid   int
	gid   int
	mode  os.FileMode
	size  int64
}

func (e *Entry) String() string {
	return fmt.Sprintf("%s %6d/%-6d %12d %s %s",
		(e.mode & 0777).String(),
		e.uid,
		e.gid,
		e.size,
		time.Unix(e.mtime, 0).Format(timeFormat),
		e.name)
}

// readMetadata reads and parses the metadata for the next entry in the archive.
func (ar *Archive) readMetadata() *Entry {
	buf := make([]byte, entryLen)
	_, err := io.ReadFull(ar.fd, buf)
	if err == io.EOF {
		// No entries left.
		return nil
	}
	if err != nil || buf[entryLen-2] != '`' || buf[entryLen-1] != '\n' {
		log.Fatal("file is not an archive: bad entry")
	}
	entry := new(Entry)
	entry.name = strings.TrimRight(string(buf[:16]), " ")
	if len(entry.name) == 0 {
		log.Fatal("file is not an archive: bad name")
	}
	buf = buf[16:]
	str := string(buf)
	get := func(width, base, bitsize int) int64 {
		v, err := strconv.ParseInt(strings.TrimRight(str[:width], " "), base, bitsize)
		if err != nil {
			log.Fatal("file is not an archive: bad number in entry: ", err)
		}
		str = str[width:]
		return v
	}
	// %-16s%-12d%-6d%-6d%-8o%-10d`
	entry.mtime = get(12, 10, 64)
	entry.uid = int(get(6, 10, 32))
	entry.gid = int(get(6, 10, 32))
	entry.mode = os.FileMode(get(8, 8, 32))
	entry.size = get(10, 10, 64)
	return entry
}

// scan scans the archive and executes the specified action on each entry.
// When action returns, the file offset is at the start of the next entry.
func (ar *Archive) scan(action func(*Entry)) {
	for {
		entry := ar.readMetadata()
		if entry == nil {
			break
		}
		action(entry)
	}
}

// listEntry prints to standard output a line describing the entry.
func listEntry(ar *Archive, entry *Entry, verbose bool) {
	if verbose {
		fmt.Fprintf(stdout, "%s\n", entry)
	} else {
		fmt.Fprintf(stdout, "%s\n", entry.name)
	}
}

// output copies the entry to the specified writer.
func (ar *Archive) output(entry *Entry, w io.Writer) {
	n, err := io.Copy(w, io.LimitReader(ar.fd, entry.size))
	if err != nil {
		log.Fatal(err)
	}
	if n != entry.size {
		log.Fatal("short file")
	}
	if entry.size&1 == 1 {
		_, err := ar.fd.Seek(1, 1)
		if err != nil {
			log.Fatal(err)
		}
	}
}

// skip skips the entry without reading it.
func (ar *Archive) skip(entry *Entry) {
	size := entry.size
	if size&1 == 1 {
		size++
	}
	_, err := ar.fd.Seek(size, 1)
	if err != nil {
		log.Fatal(err)
	}
}

// match reports whether the entry matches the argument list.
// If it does, it also drops the file from the to-be-processed list.
func (ar *Archive) match(entry *Entry) bool {
	if ar.matchAll {
		return true
	}
	for i, name := range ar.files {
		if entry.name == name {
			copy(ar.files[i:], ar.files[i+1:])
			ar.files = ar.files[:len(ar.files)-1]
			return true
		}
	}
	return false
}

// addFiles adds files to the archive. The archive is known to be
// sane and we are positioned at the end. No attempt is made
// to check for existing files.
func (ar *Archive) addFiles() {
	if len(ar.files) == 0 {
		usage()
	}
	for _, file := range ar.files {
		if verbose {
			fmt.Printf("%s\n", file)
		}
		fd, err := os.Open(file)
		if err != nil {
			log.Fatal(err)
		}
		ar.addFile(fd)
	}
	ar.files = nil
}

// FileLike abstracts the few methods we need, so we can test without needing real files.
type FileLike interface {
	Name() string
	Stat() (os.FileInfo, error)
	Read([]byte) (int, error)
	Close() error
}

// addFile adds a single file to the archive
func (ar *Archive) addFile(fd FileLike) {
	defer fd.Close()
	// Format the entry.
	// First, get its info.
	info, err := fd.Stat()
	if err != nil {
		log.Fatal(err)
	}
	// mtime, uid, gid are all zero so repeated builds produce identical output.
	mtime := int64(0)
	uid := 0
	gid := 0
	ar.startFile(info.Name(), mtime, uid, gid, info.Mode(), info.Size())
	n64, err := io.Copy(ar.fd, fd)
	if err != nil {
		log.Fatal("writing file: ", err)
	}
	if n64 != info.Size() {
		log.Fatalf("writing file: wrote %d bytes; file is size %d", n64, info.Size())
	}
	ar.endFile()
}

// startFile writes the archive entry header.
func (ar *Archive) startFile(name string, mtime int64, uid, gid int, mode os.FileMode, size int64) {
	n, err := fmt.Fprintf(ar.fd, entryHeader, exactly16Bytes(name), mtime, uid, gid, mode, size)
	if err != nil || n != entryLen {
		log.Fatal("writing entry header: ", err)
	}
	ar.pad = int(size & 1)
}

// endFile writes the archive entry tail (a single byte of padding, if the file size was odd).
func (ar *Archive) endFile() {
	if ar.pad != 0 {
		_, err := ar.fd.Write([]byte{0})
		if err != nil {
			log.Fatal("writing archive: ", err)
		}
		ar.pad = 0
	}
}

// addPkgdef adds the __.PKGDEF file to the archive, copied
// from the first Go object file on the file list, if any.
// The archive is known to be empty.
func (ar *Archive) addPkgdef() {
	for _, file := range ar.files {
		pkgdef, err := readPkgdef(file)
		if err != nil {
			continue
		}
		if verbose {
			fmt.Printf("__.PKGDEF # %s\n", file)
		}
		ar.startFile("__.PKGDEF", 0, 0, 0, 0644, int64(len(pkgdef)))
		_, err = ar.fd.Write(pkgdef)
		if err != nil {
			log.Fatal("writing __.PKGDEF: ", err)
		}
		ar.endFile()
		break
	}
}

// readPkgdef extracts the __.PKGDEF data from a Go object file.
func readPkgdef(file string) (data []byte, err error) {
	f, err := os.Open(file)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	// Read from file, collecting header for __.PKGDEF.
	// The header is from the beginning of the file until a line
	// containing just "!". The first line must begin with "go object ".
	rbuf := bufio.NewReader(f)
	var wbuf bytes.Buffer
	for {
		line, err := rbuf.ReadBytes('\n')
		if err != nil {
			return nil, err
		}
		if wbuf.Len() == 0 && !bytes.HasPrefix(line, []byte("go object ")) {
			return nil, errors.New("not a Go object file")
		}
		if bytes.Equal(line, []byte("!\n")) {
			break
		}
		wbuf.Write(line)
	}
	return wbuf.Bytes(), nil
}

// exactly16Bytes truncates the string if necessary so it is at most 16 bytes long,
// then pads the result with spaces to be exactly 16 bytes.
// Fmt uses runes for its width calculation, but we need bytes in the entry header.
func exactly16Bytes(s string) string {
	for len(s) > 16 {
		_, wid := utf8.DecodeLastRuneInString(s)
		s = s[:len(s)-wid]
	}
	const sixteenSpaces = "                "
	s += sixteenSpaces[:16-len(s)]
	return s
}

// Finally, the actual commands. Each is an action.

// can be modified for testing.
var stdout io.Writer = os.Stdout

// printContents implements the 'p' command.
func (ar *Archive) printContents(entry *Entry) {
	if ar.match(entry) {
		if verbose {
			listEntry(ar, entry, false)
		}
		ar.output(entry, stdout)
	} else {
		ar.skip(entry)
	}
}

// skipContents implements the first part of the 'r' command.
// It just scans the archive to make sure it's intact.
func (ar *Archive) skipContents(entry *Entry) {
	ar.skip(entry)
}

// tableOfContents implements the 't' command.
func (ar *Archive) tableOfContents(entry *Entry) {
	if ar.match(entry) {
		listEntry(ar, entry, verbose)
	}
	ar.skip(entry)
}

// extractContents implements the 'x' command.
func (ar *Archive) extractContents(entry *Entry) {
	if ar.match(entry) {
		if verbose {
			listEntry(ar, entry, false)
		}
		fd, err := os.OpenFile(entry.name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, entry.mode)
		if err != nil {
			log.Fatal(err)
		}
		ar.output(entry, fd)
		fd.Close()
	} else {
		ar.skip(entry)
	}
}
