// ApplyDiff applies the new layer on top of the root, if parent does not exist with will return a ErrApplyDiffFallback error. func (d *Driver) ApplyDiff(id string, parent string, diff archive.Reader) (size int64, err error) { dir := d.dir(id) if parent == "" { return 0, ErrApplyDiffFallback } parentRootDir := path.Join(d.dir(parent), "root") if _, err := os.Stat(parentRootDir); err != nil { return 0, ErrApplyDiffFallback } // We now know there is a parent, and it has a "root" directory containing // the full root filesystem. We can just hardlink it and apply the // layer. This relies on two things: // 1) ApplyDiff is only run once on a clean (no writes to upper layer) container // 2) ApplyDiff doesn't do any in-place writes to files (would break hardlinks) // These are all currently true and are not expected to break tmpRootDir, err := ioutil.TempDir(dir, "tmproot") if err != nil { return 0, err } defer func() { if err != nil { os.RemoveAll(tmpRootDir) } else { os.RemoveAll(path.Join(dir, "upper")) os.RemoveAll(path.Join(dir, "work")) os.RemoveAll(path.Join(dir, "merged")) os.RemoveAll(path.Join(dir, "lower-id")) } }() if err = copyDir(parentRootDir, tmpRootDir, copyHardlink); err != nil { return 0, err } options := &archive.TarOptions{UIDMaps: d.uidMaps, GIDMaps: d.gidMaps} if size, err = chrootarchive.ApplyUncompressedLayer(tmpRootDir, diff, options); err != nil { return 0, err } rootDir := path.Join(dir, "root") if err := os.Rename(tmpRootDir, rootDir); err != nil { return 0, err } return }
// ApplyDiff extracts the changeset from the given diff into the // layer with the specified id and parent, returning the size of the // new layer in bytes. // The layer should not be mounted when calling this function func (d *Driver) ApplyDiff(id, parent string, diff archive.Reader) (int64, error) { if d.info.Flavour == diffDriver { start := time.Now().UTC() logrus.Debugf("WindowsGraphDriver ApplyDiff: Start untar layer") destination := d.dir(id) destination = filepath.Dir(destination) size, err := chrootarchive.ApplyUncompressedLayer(destination, diff, nil) if err != nil { return 0, err } logrus.Debugf("WindowsGraphDriver ApplyDiff: Untar time: %vs", time.Now().UTC().Sub(start).Seconds()) return size, nil } var layerChain []string if parent != "" { rPId, err := d.resolveID(parent) if err != nil { return 0, err } parentChain, err := d.getLayerChain(rPId) if err != nil { return 0, err } parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId) if err != nil { return 0, err } layerChain = append(layerChain, parentPath) layerChain = append(layerChain, parentChain...) } size, err := d.importLayer(id, diff, layerChain) if err != nil { return 0, err } if err = d.setLayerChain(id, layerChain); err != nil { return 0, err } return size, nil }
// ApplyDiff extracts the changeset from the given diff into the // layer with the specified id and parent, returning the size of the // new layer in bytes. func (gdw *naiveDiffDriver) ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error) { driver := gdw.ProtoDriver // Mount the root filesystem so we can apply the diff/layer. layerFs, err := driver.Get(id, "") if err != nil { return } defer driver.Put(id) start := time.Now().UTC() logrus.Debugf("Start untar layer") if size, err = chrootarchive.ApplyUncompressedLayer(layerFs, diff); err != nil { return } logrus.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds()) return }