diff --git a/tar-read.go b/tar-read.go index 5c917d9..98b5333 100644 --- a/tar-read.go +++ b/tar-read.go @@ -2,9 +2,13 @@ package main import ( "archive/tar" + "bytes" + "crypto/md5" + "encoding/json" "fmt" "io" "os" + "strings" ) func main() { @@ -22,7 +26,64 @@ func main() { // } tarReader := tar.NewReader(f) + targetName := "manifest.json" + var m Manifest + var trees []*Tree + for { + header, err := tarReader.Next() + if err == io.EOF { + break + } + + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + name := header.Name + if name == targetName { + m = handleManifest(tarReader, header) + } + + switch header.Typeflag { + case tar.TypeDir: + continue + case tar.TypeReg: + //fmt.Println("File: ", name) + if strings.HasSuffix(name, "layer.tar") { + fmt.Println("Containing:") + tree := NewTree() + tree.name = strings.TrimSuffix(name, "layer.tar") + fileInfos := getFileList(tarReader, header) + for _, element := range fileInfos { + tree.AddPath(element.path, element) + } + trees = append(trees, tree) + } + default: + fmt.Printf("%s : %c %s %s\n", + "hmmm?", + header.Typeflag, + "in file", + name, + ) + } + } + fmt.Printf("%+v\n", m) + fmt.Printf("%+v\n", trees) +} + +func getFileList(parentReader *tar.Reader, h *tar.Header) []FileChangeInfo { + var files []FileChangeInfo + size := h.Size + tarredBytes := make([]byte, size) + _, err := parentReader.Read(tarredBytes) + if err != nil { + panic(err) + } + r := bytes.NewReader(tarredBytes) + tarReader := tar.NewReader(r) for { header, err := tarReader.Next() @@ -39,11 +100,12 @@ func main() { switch header.Typeflag { case tar.TypeDir: - continue + files = append(files, makeEntry(tarReader, header, name)) case tar.TypeReg: - fmt.Println("File: ", name) - // show the contents - // io.Copy(os.Stdout, tarReader) + files = append(files, makeEntry(tarReader, header, name)) + continue + case tar.TypeSymlink: + files = append(files, makeEntry(tarReader, header, name)) default: fmt.Printf("%s : %c %s %s\n", "hmmm?", @@ -53,4 +115,55 @@ func main() { ) } } + return files +} + +func makeEntry(r *tar.Reader, h *tar.Header, path string) FileChangeInfo { + if h.Typeflag == tar.TypeDir { + return FileChangeInfo{ + path: path, + typeflag: h.Typeflag, + md5sum: zeros, + } + } + fileBytes := make([]byte, h.Size) + _, err := r.Read(fileBytes) + if err != nil && err != io.EOF { + panic(err) + } + hash := md5.Sum(fileBytes) + return FileChangeInfo{ + path: path, + typeflag: h.Typeflag, + md5sum: hash, + } +} + +var zeros = [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +type FileChangeInfo struct { + path string + typeflag byte + md5sum [16]byte +} + +type Manifest struct { + Config string + RepoTags []string + Layers []string +} + +func handleManifest(r *tar.Reader, header *tar.Header) Manifest { + size := header.Size + manifestBytes := make([]byte, size) + _, err := r.Read(manifestBytes) + if err != nil { + panic(err) + } + var m [1]Manifest + err = json.Unmarshal(manifestBytes, &m) + if err != nil { + panic(err) + } + return m[0] } diff --git a/tree.go b/tree.go index 83159c7..ebcf817 100644 --- a/tree.go +++ b/tree.go @@ -15,6 +15,7 @@ const ( type Tree struct { root *Node size int + name string } type Node struct {