Skip to content

Commit ec2b20d

Browse files
committed
update
1 parent 552c4de commit ec2b20d

File tree

3 files changed

+75
-9
lines changed

3 files changed

+75
-9
lines changed

analyzer/analyzer.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package analyzer
22

33
import (
4-
"os"
5-
"path/filepath"
4+
"io"
65

76
"github.com/knqyf263/fanal/extractor"
87
"github.com/pkg/errors"
@@ -59,11 +58,9 @@ func RequiredFilenames() []string {
5958
return filenames
6059
}
6160

62-
func Analyze(dir string) (filesMap extractor.FilesMap, err error) {
61+
func Analyze(r io.ReadCloser) (filesMap extractor.FilesMap, err error) {
6362
extractor := extractor.DockerExtractor{}
64-
file, _ := os.Open(filepath.Join(dir, "layer.tar"))
65-
66-
filesMap, err = extractor.ExtractFiles(file, RequiredFilenames())
63+
filesMap, err = extractor.Extract(r, RequiredFilenames())
6764
if err != nil {
6865
return nil, errors.Wrap(err, "Failed to extract files")
6966
}

cmd/fanal/main.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,38 @@
11
package main
22

33
import (
4+
"flag"
45
"log"
56
"os"
67

8+
"golang.org/x/crypto/ssh/terminal"
9+
710
"github.com/knqyf263/fanal/analyzer"
811
_ "github.com/knqyf263/fanal/analyzer/os/alpine"
912
_ "github.com/knqyf263/fanal/analyzer/pkg/apk"
1013
)
1114

1215
func main() {
13-
dir, err := os.Getwd()
16+
tarPath := flag.String("f", "-", "layer.tar path")
17+
flag.Parse()
18+
rc, err := openStream(*tarPath)
1419
if err != nil {
1520
log.Fatal(err)
1621
}
1722

18-
files, _ := analyzer.Analyze(dir)
23+
files, _ := analyzer.Analyze(rc)
1924
analyzer.GetOS(files)
2025
analyzer.GetPackages(files)
2126
}
27+
28+
func openStream(path string) (*os.File, error) {
29+
if path == "-" {
30+
if terminal.IsTerminal(0) {
31+
flag.Usage()
32+
os.Exit(64)
33+
} else {
34+
return os.Stdin, nil
35+
}
36+
}
37+
return os.Open(path)
38+
}

extractor/docker.go

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,66 @@ package extractor
22

33
import (
44
"archive/tar"
5+
"encoding/json"
56
"io"
67
"io/ioutil"
78
"path"
9+
"path/filepath"
10+
"strings"
811
)
912

13+
type manifest struct {
14+
Config string `json:"Config"`
15+
RepoTags []string `json:"RepoTags"`
16+
Layers []string `json:"Layers"`
17+
}
18+
1019
type DockerExtractor struct{}
1120

12-
func (d DockerExtractor) ExtractFiles(layer io.ReadCloser, filenames []string) (FilesMap, error) {
21+
func (d DockerExtractor) Extract(r io.ReadCloser, filenames []string) (FilesMap, error) {
22+
manifests := make([]manifest, 0)
23+
filesInLayers := make(map[string]FilesMap)
24+
tr := tar.NewReader(r)
25+
for {
26+
header, err := tr.Next()
27+
if err == io.EOF {
28+
break
29+
}
30+
if err != nil {
31+
return nil, ErrCouldNotExtract
32+
}
33+
switch {
34+
case header.Name == "manifest.json":
35+
if err := json.NewDecoder(tr).Decode(&manifests); err != nil {
36+
return nil, err
37+
}
38+
case strings.HasSuffix(header.Name, ".tar"):
39+
layerID := filepath.Base(filepath.Dir(header.Name))
40+
files, err := d.ExtractFiles(tr, filenames)
41+
if err != nil {
42+
return nil, err
43+
}
44+
filesInLayers[layerID] = files
45+
//case strings.HasSuffix(header.Name, ".json"):
46+
// if err := json.NewDecoder(tr).Decode(&imageMeta); err != nil {
47+
// return nil, err
48+
// }
49+
// imageMetas[header.Name] = imageMeta
50+
default:
51+
}
52+
}
53+
filesMap := map[string][]byte{}
54+
for _, layerID := range manifests[0].Layers {
55+
layerID := strings.Split(layerID, "/")[0]
56+
for k, v := range filesInLayers[layerID] {
57+
filesMap[k] = v
58+
}
59+
}
60+
61+
return filesMap, nil
62+
63+
}
64+
func (d DockerExtractor) ExtractFiles(layer io.Reader, filenames []string) (FilesMap, error) {
1365
data := make(map[string][]byte)
1466

1567
tr := tar.NewReader(layer)

0 commit comments

Comments
 (0)