func TestChrootTarUntar(t *testing.T) { tmpdir, err := ioutil.TempDir("", "docker-TestChrootTarUntar") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) src := filepath.Join(tmpdir, "src") if err := os.MkdirAll(src, 0700); err != nil { t.Fatal(err) } if err := ioutil.WriteFile(filepath.Join(src, "toto"), []byte("hello toto"), 0644); err != nil { t.Fatal(err) } if err := ioutil.WriteFile(filepath.Join(src, "lolo"), []byte("hello lolo"), 0644); err != nil { t.Fatal(err) } stream, err := archive.Tar(src, archive.Uncompressed) if err != nil { t.Fatal(err) } dest := filepath.Join(tmpdir, "src") if err := os.MkdirAll(dest, 0700); err != nil { t.Fatal(err) } if err := Untar(stream, dest, &archive.TarOptions{Excludes: []string{"lolo"}}); err != nil { t.Fatal(err) } }
func TestChrootApplyDotDotFile(t *testing.T) { tmpdir, err := ioutil.TempDir("", "docker-TestChrootApplyDotDotFile") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) src := filepath.Join(tmpdir, "src") if err := os.MkdirAll(src, 0700); err != nil { t.Fatal(err) } if err := ioutil.WriteFile(filepath.Join(src, "..gitme"), []byte(""), 0644); err != nil { t.Fatal(err) } stream, err := archive.Tar(src, archive.Uncompressed) if err != nil { t.Fatal(err) } dest := filepath.Join(tmpdir, "dest") if err := os.MkdirAll(dest, 0700); err != nil { t.Fatal(err) } if _, err := ApplyLayer(dest, stream); err != nil { t.Fatal(err) } }
// Diff produces an archive of the changes between the specified // layer and its parent layer which may be "". func (gdw *NaiveDiffDriver) Diff(id, parent string) (arch archive.Archive, err error) { driver := gdw.ProtoDriver layerFs, err := driver.Get(id, "") if err != nil { return nil, err } defer func() { if err != nil { driver.Put(id) } }() if parent == "" { archive, err := archive.Tar(layerFs, archive.Uncompressed) if err != nil { return nil, err } return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() driver.Put(id) return err }), nil } parentFs, err := driver.Get(parent, "") if err != nil { return nil, err } defer driver.Put(parent) changes, err := archive.ChangesDirs(layerFs, parentFs) if err != nil { return nil, err } archive, err := archive.ExportChanges(layerFs, changes, gdw.uidMaps, gdw.gidMaps) if err != nil { return nil, err } return ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() driver.Put(id) return err }), nil }
// CmdImageExport exports all images with the given tag. All versions // containing the same tag are exported. The resulting output is an // uncompressed tar ball. // name is the set of tags to export. // out is the writer where the images are written to. func (s *TagStore) CmdImageExport(job *engine.Job) engine.Status { if len(job.Args) < 1 { return job.Errorf("Usage: %s IMAGE [IMAGE...]\n", job.Name) } // get image json tempdir, err := ioutil.TempDir("", "docker-export-") if err != nil { return job.Error(err) } defer os.RemoveAll(tempdir) rootRepoMap := map[string]Repository{} addKey := func(name string, tag string, id string) { log.Debugf("add key [%s:%s]", name, tag) if repo, ok := rootRepoMap[name]; !ok { rootRepoMap[name] = Repository{tag: id} } else { repo[tag] = id } } for _, name := range job.Args { log.Debugf("Serializing %s", name) rootRepo := s.Repositories[name] if rootRepo != nil { // this is a base repo name, like 'busybox' for tag, id := range rootRepo { addKey(name, tag, id) if err := s.exportImage(job.Eng, id, tempdir); err != nil { return job.Error(err) } } } else { img, err := s.LookupImage(name) if err != nil { return job.Error(err) } if img != nil { // This is a named image like 'busybox:latest' repoName, repoTag := parsers.ParseRepositoryTag(name) // check this length, because a lookup of a truncated has will not have a tag // and will not need to be added to this map if len(repoTag) > 0 { addKey(repoName, repoTag, img.ID) } if err := s.exportImage(job.Eng, img.ID, tempdir); err != nil { return job.Error(err) } } else { // this must be an ID that didn't get looked up just right? if err := s.exportImage(job.Eng, name, tempdir); err != nil { return job.Error(err) } } } log.Debugf("End Serializing %s", name) } // write repositories, if there is something to write if len(rootRepoMap) > 0 { rootRepoJson, _ := json.Marshal(rootRepoMap) if err := ioutil.WriteFile(path.Join(tempdir, "repositories"), rootRepoJson, os.FileMode(0644)); err != nil { return job.Error(err) } } else { log.Debugf("There were no repositories to write") } fs, err := archive.Tar(tempdir, archive.Uncompressed) if err != nil { return job.Error(err) } defer fs.Close() if _, err := io.Copy(job.Stdout, fs); err != nil { return job.Error(err) } log.Debugf("End export job: %s", job.Name) return engine.StatusOK }
// ImageExport exports list of images to a output stream specified in the // config. The exported images are archived into a tar when written to the // output stream. All images with the given tag and all versions containing the // same tag are exported. names is the set of tags to export, and outStream // is the writer which the images are written to. func (s *TagStore) ImageExport(names []string, outStream io.Writer) error { // get image json tempdir, err := ioutil.TempDir("", "docker-export-") if err != nil { return err } defer os.RemoveAll(tempdir) rootRepoMap := map[string]Repository{} addKey := func(name string, tag string, id string) { logrus.Debugf("add key [%s:%s]", name, tag) if repo, ok := rootRepoMap[name]; !ok { rootRepoMap[name] = Repository{tag: id} } else { repo[tag] = id } } for _, name := range names { name = registry.NormalizeLocalName(name) logrus.Debugf("Serializing %s", name) rootRepo := s.Repositories[name] if rootRepo != nil { // this is a base repo name, like 'busybox' for tag, id := range rootRepo { addKey(name, tag, id) if err := s.exportImage(id, tempdir); err != nil { return err } } } else { img, err := s.LookupImage(name) if err != nil { return err } if img != nil { // This is a named image like 'busybox:latest' repoName, repoTag := parsers.ParseRepositoryTag(name) // Skip digests on save if _, err := digest.ParseDigest(repoTag); err == nil { repoTag = "" } // check this length, because a lookup of a truncated has will not have a tag // and will not need to be added to this map if len(repoTag) > 0 { addKey(repoName, repoTag, img.ID) } if err := s.exportImage(img.ID, tempdir); err != nil { return err } } else { // this must be an ID that didn't get looked up just right? if err := s.exportImage(name, tempdir); err != nil { return err } } } logrus.Debugf("End Serializing %s", name) } // write repositories, if there is something to write if len(rootRepoMap) > 0 { f, err := os.OpenFile(filepath.Join(tempdir, "repositories"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { f.Close() return err } if err := json.NewEncoder(f).Encode(rootRepoMap); err != nil { return err } if err := f.Close(); err != nil { return err } if err := os.Chtimes(filepath.Join(tempdir, "repositories"), time.Unix(0, 0), time.Unix(0, 0)); err != nil { return err } } else { logrus.Debugf("There were no repositories to write") } fs, err := archive.Tar(tempdir, archive.Uncompressed) if err != nil { return err } defer fs.Close() if _, err := io.Copy(outStream, fs); err != nil { return err } logrus.Debugf("End export image") return nil }