1
Fork 0

Rootfs is now a struct

main
Motiejus Jakštys 2021-05-24 00:11:58 +03:00
parent d372a538ce
commit 98373a151d
3 changed files with 22 additions and 20 deletions

View File

@ -21,11 +21,11 @@ func (r *CmdRootFS) Execute(args []string) (err error) {
return errors.New("too many args")
}
in, err := os.Open(string(r.PositionalArgs.Infile))
rd, err := os.Open(string(r.PositionalArgs.Infile))
if err != nil {
return err
}
defer func() { err = multierr.Append(err, in.Close()) }()
defer func() { err = multierr.Append(err, rd.Close()) }()
var out *os.File
outf := string(r.PositionalArgs.Outfile)
@ -39,5 +39,5 @@ func (r *CmdRootFS) Execute(args []string) (err error) {
}
defer func() { err = multierr.Append(err, out.Close()) }()
return rootfs.RootFS(in, out)
return rootfs.New(rd).WriteTo(out)
}

View File

@ -27,17 +27,19 @@ type dockerManifestJSON []struct {
Layers []string `json:"Layers"`
}
// RootFS accepts a docker layer tarball and writes it to outfile.
// 1. create map[string]io.ReadSeeker for each layer.
// 2. parse manifest.json and get the layer order.
// 3. go through each layer in order and write:
// a) to an ordered slice: the file name.
// b) to an FS map: where does the file come from?
// I) layer name
// II) offset (0 being the first file in the layer)
// 4. go through
func RootFS(in io.ReadSeeker, wr io.Writer) (err error) {
tr := tar.NewReader(in)
// RootFS accepts a docker layer tarball and flattens it.
type RootFS struct {
rd io.ReadSeeker
}
// New creates a new RootFS'er.
func New(rd io.ReadSeeker) *RootFS {
return &RootFS{rd: rd}
}
// WriteTo writes a docker image to an open tarball.
func (r *RootFS) WriteTo(wr io.Writer) (err error) {
tr := tar.NewReader(r.rd)
tw := tar.NewWriter(wr)
defer func() { err = multierr.Append(err, tw.Close()) }()
@ -63,7 +65,7 @@ func RootFS(in io.ReadSeeker, wr io.Writer) (err error) {
return fmt.Errorf("decode %s: %w", _manifestJSON, err)
}
case strings.HasSuffix(hdr.Name, _layerSuffix):
here, err := in.Seek(0, io.SeekCurrent)
here, err := r.rd.Seek(0, io.SeekCurrent)
if err != nil {
return err
}
@ -93,10 +95,10 @@ func RootFS(in io.ReadSeeker, wr io.Writer) (err error) {
// iterate over all files, construct `file2layer`, `whreaddir`, `wh`
for i, offset := range layers {
if _, err := in.Seek(offset, io.SeekStart); err != nil {
if _, err := r.rd.Seek(offset, io.SeekStart); err != nil {
return err
}
tr = tar.NewReader(in)
tr = tar.NewReader(r.rd)
for {
hdr, err := tr.Next()
if err == io.EOF {
@ -134,10 +136,10 @@ func RootFS(in io.ReadSeeker, wr io.Writer) (err error) {
// iterate through all layers, all files, and write files.
for i, offset := range layers {
if _, err := in.Seek(offset, io.SeekStart); err != nil {
if _, err := r.rd.Seek(offset, io.SeekStart); err != nil {
return err
}
tr = tar.NewReader(in)
tr = tar.NewReader(r.rd)
for {
hdr, err := tr.Next()
if err == io.EOF {

View File

@ -177,7 +177,7 @@ func TestRootFS(t *testing.T) {
in := bytes.NewReader(tt.image.Bytes())
out := bytes.Buffer{}
err := RootFS(in, &out)
err := New(in).WriteTo(&out)
if tt.wantErr != "" {
assert.EqualError(t, err, tt.wantErr)
return