reading files using size and offsets

main
Motiejus Jakštys 2021-05-24 00:11:58 +03:00
parent b622d991cf
commit 76ab2a9c82
2 changed files with 48 additions and 41 deletions

View File

@ -35,6 +35,12 @@ type (
Env []string Env []string
} }
// offsetSize is a tuple which stores file offset and size
offsetSize struct {
offset int64
size int64
}
// dockerManifest is manifest.json // dockerManifest is manifest.json
dockerManifest []struct { dockerManifest []struct {
Config string `json:"Config"` Config string `json:"Config"`
@ -93,7 +99,7 @@ func (l lxcConfig) WriteTo(wr io.Writer) error {
func getDockerConfig(rd io.ReadSeeker) (dockerConfig, error) { func getDockerConfig(rd io.ReadSeeker) (dockerConfig, error) {
tr := tar.NewReader(rd) tr := tar.NewReader(rd)
// get offsets to all json files rd the archive // get offsets to all json files rd the archive
jsonOffsets := map[string]int64{} jsonOffsets := map[string]offsetSize{}
for { for {
hdr, err := tr.Next() hdr, err := tr.Next()
if err == io.EOF { if err == io.EOF {
@ -109,7 +115,10 @@ func getDockerConfig(rd io.ReadSeeker) (dockerConfig, error) {
if err != nil { if err != nil {
return dockerConfig{}, err return dockerConfig{}, err
} }
jsonOffsets[hdr.Name] = here jsonOffsets[hdr.Name] = offsetSize{
offset: here,
size: hdr.Size,
}
} }
// manifest is the docker manifest rd the image // manifest is the docker manifest rd the image
@ -129,21 +138,17 @@ func getDockerConfig(rd io.ReadSeeker) (dockerConfig, error) {
return config, nil return config, nil
} }
//TODO: don't seek to files, read them. func parseJSON(rd io.ReadSeeker, offsets map[string]offsetSize, fname string, c interface{}) error {
func parseJSON(rd io.ReadSeeker, offsets map[string]int64, fname string, c interface{}) error { osize, ok := offsets[fname]
configOffset, ok := offsets[fname]
fmt.Printf("jumping to %s in %x\n", fname, configOffset)
if !ok { if !ok {
return fmt.Errorf("file %s not found", fname) return fmt.Errorf("file %s not found", fname)
} }
if _, err := rd.Seek(configOffset, io.SeekStart); err != nil { if _, err := rd.Seek(osize.offset, io.SeekStart); err != nil {
return fmt.Errorf("seek to %s: %w", fname, err) return fmt.Errorf("seek to %s: %w", fname, err)
} }
tr := tar.NewReader(rd)
if _, err := tr.Next(); err != nil { lrd := io.LimitReader(rd, osize.size)
return err dec := json.NewDecoder(lrd)
}
dec := json.NewDecoder(tr)
if err := dec.Decode(c); err != nil { if err := dec.Decode(c); err != nil {
return fmt.Errorf("decode %s: %w", fname, err) return fmt.Errorf("decode %s: %w", fname, err)
} }

View File

@ -4,6 +4,7 @@ import (
"archive/tar" "archive/tar"
"bytes" "bytes"
"encoding/json" "encoding/json"
"strings"
"testing" "testing"
"github.com/motiejus/code/undocker/internal/tartest" "github.com/motiejus/code/undocker/internal/tartest"
@ -23,35 +24,37 @@ func TestLXCConfig(t *testing.T) {
docker: dockerConfig{ docker: dockerConfig{
Architecture: "amd64", Architecture: "amd64",
}, },
want: `lxc.include = LXC_TEMPLATE_CONFIG/common.conf want: strings.Join([]string{
lxc.architecture = amd64 `lxc.include = LXC_TEMPLATE_CONFIG/common.conf`,
lxc.execute.cmd = '/bin/sh' `lxc.architecture = amd64`,
`, `lxc.execute.cmd = '/bin/sh'`,
``,
}, "\n"),
}, },
/* {
{ name: "all fields",
name: "all fields", docker: dockerConfig{
docker: dockerConfig{ Architecture: "amd64",
Architecture: "amd64", Config: dockerConfigConfig{
Config: dockerConfigConfig{ Entrypoint: []string{"/entrypoint.sh"},
Entrypoint: []string{"/entrypoint.sh"}, Cmd: []string{"/bin/sh", "-c", "echo foo"},
Cmd: []string{"/bin/sh", "-c", "echo foo"}, WorkingDir: "/x",
WorkingDir: "/x", Env: []string{
Env: []string{ `LONGNAME="Foo Bar"`,
`LONGNAME="Foo Bar"`, "SHELL=/bin/tcsh",
"SHELL=/bin/tcsh",
},
},
},
want: `lxc.include = LXC_TEMPLATE_CONFIG/common.conf
lxc.architecture = amd64
lxc.execute.cmd = '/entrypoint.sh /bin/sh -c echo foo'
lxc.init.cwd = /x
lxc.environment = LONGNAME="Foo Bar"
lxc.environment = SHELL=/bin/tcsh
`,
}, },
*/ },
},
want: strings.Join([]string{
`lxc.include = LXC_TEMPLATE_CONFIG/common.conf`,
`lxc.architecture = amd64`,
`lxc.execute.cmd = '/entrypoint.sh /bin/sh -c echo foo'`,
`lxc.init.cwd = /x`,
`lxc.environment = LONGNAME="Foo Bar"`,
`lxc.environment = SHELL=/bin/tcsh`,
``,
}, "\n"),
},
} }
for _, tt := range tests { for _, tt := range tests {
@ -60,10 +63,9 @@ lxc.execute.cmd = '/bin/sh'
Name: "manifest.json", Name: "manifest.json",
Contents: bytes.NewBufferString(`[{"Config":"config.json"}]`), Contents: bytes.NewBufferString(`[{"Config":"config.json"}]`),
} }
_ = manifest
archive := tartest.Tarball{ archive := tartest.Tarball{
manifest, manifest,
//tt.docker, tt.docker,
} }
in := bytes.NewReader(archive.Buffer().Bytes()) in := bytes.NewReader(archive.Buffer().Bytes())
var buf bytes.Buffer var buf bytes.Buffer