// 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
	go doc 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.Fatalf("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.Fatalf("%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, io.SeekCurrent)
		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, io.SeekCurrent)
	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)
	}
}
