func (s *Store) Add(img *registry.Image) (err error) { if err := s.lock(img.ID); err != nil { return err } defer s.unlock(img.ID) if s.Exists(img.ID) { return ErrExists } defer func() { if err != nil { // cleanup if we fail s.driver.Remove(img.ID) } }() tmp, err := s.tempDir() if err != nil { return err } defer os.RemoveAll(tmp) if err := s.driver.Create(img.ID, img.ParentID); err != nil { return err } layer, err := s.driver.Get(img.ID, "") if err != nil { return err } defer s.driver.Put(img.ID) if differ, ok := s.driver.(graphdriver.Differ); ok { if err := differ.ApplyDiff(img.ID, img); err != nil { return err } } else { if err := archive.ApplyLayer(layer, img); err != nil { return err } } if err := ioutil.WriteFile(filepath.Join(tmp, "layersize"), []byte{'0'}, 0600); err != nil { return err } f, err := os.OpenFile(filepath.Join(tmp, "json"), os.O_RDWR|os.O_CREATE, 0600) if err != nil { return err } defer f.Close() if err := json.NewEncoder(f).Encode(img); err != nil { return err } return os.Rename(tmp, s.root(img.ID)) }
func StoreImage(img *Image, jsonData []byte, layerData archive.Archive, root, layer string) error { // Store the layer var ( size int64 err error driver = img.graph.driver ) if err := os.MkdirAll(layer, 0755); err != nil { return err } // If layerData is not nil, unpack it into the new layer if layerData != nil { if differ, ok := driver.(graphdriver.Differ); ok { if err := differ.ApplyDiff(img.ID, layerData); err != nil { return err } if size, err = differ.DiffSize(img.ID); err != nil { return err } } else { start := time.Now().UTC() utils.Debugf("Start untar layer") if err := archive.ApplyLayer(layer, layerData); err != nil { return err } utils.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds()) if img.Parent == "" { if size, err = utils.TreeSize(layer); err != nil { return err } } else { parent, err := driver.Get(img.Parent) if err != nil { return err } defer driver.Put(img.Parent) changes, err := archive.ChangesDirs(layer, parent) if err != nil { return err } size = archive.ChangesSize(layer, changes) } } } img.Size = size if err := img.SaveSize(root); err != nil { return err } // If raw json is provided, then use it if jsonData != nil { if err := ioutil.WriteFile(jsonPath(root), jsonData, 0600); err != nil { return err } } else { if jsonData, err = json.Marshal(img); err != nil { return err } if err := ioutil.WriteFile(jsonPath(root), jsonData, 0600); err != nil { return err } } return nil }