1package main
2
3import (
4	"bufio"
5	"compress/gzip"
6	"io"
7	"os"
8	"path/filepath"
9
10	"github.com/Microsoft/go-winio"
11	"github.com/Microsoft/hcsshim/internal/appargs"
12	"github.com/Microsoft/hcsshim/internal/ociwclayer"
13	"github.com/urfave/cli"
14)
15
16var importCommand = cli.Command{
17	Name:  "import",
18	Usage: "imports a layer from a tar file",
19	Flags: []cli.Flag{
20		cli.StringSliceFlag{
21			Name:  "layer, l",
22			Usage: "paths to the read-only parent layers",
23		},
24		cli.StringFlag{
25			Name:  "input, i",
26			Usage: "input layer tar (defaults to stdin)",
27		},
28	},
29	ArgsUsage: "<layer path>",
30	Before:    appargs.Validate(appargs.NonEmptyString),
31	Action: func(context *cli.Context) (err error) {
32		path, err := filepath.Abs(context.Args().First())
33		if err != nil {
34			return err
35		}
36
37		layers, err := normalizeLayers(context.StringSlice("layer"), false)
38		if err != nil {
39			return err
40		}
41
42		fp := context.String("input")
43		f := os.Stdin
44		if fp != "" {
45			f, err = os.Open(fp)
46			if err != nil {
47				return err
48			}
49			defer f.Close()
50		}
51		r, err := addDecompressor(f)
52		if err != nil {
53			return err
54		}
55		err = winio.EnableProcessPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege})
56		if err != nil {
57			return err
58		}
59		_, err = ociwclayer.ImportLayer(r, path, layers)
60		return err
61	},
62}
63
64func addDecompressor(r io.Reader) (io.Reader, error) {
65	b := bufio.NewReader(r)
66	hdr, err := b.Peek(3)
67	if err != nil {
68		return nil, err
69	}
70	if hdr[0] == 0x1f && hdr[1] == 0x8b && hdr[2] == 8 {
71		return gzip.NewReader(b)
72	}
73	return b, nil
74}
75