mirror of
https://github.com/containers/skopeo.git
synced 2025-08-01 23:07:51 +00:00
*: update c/storage
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
parent
fe67466701
commit
08504d913c
31
vendor/github.com/containers/storage/containers.go
generated
vendored
31
vendor/github.com/containers/storage/containers.go
generated
vendored
@ -93,7 +93,7 @@ type ContainerStore interface {
|
|||||||
type containerStore struct {
|
type containerStore struct {
|
||||||
lockfile Locker
|
lockfile Locker
|
||||||
dir string
|
dir string
|
||||||
containers []Container
|
containers []*Container
|
||||||
idindex *truncindex.TruncIndex
|
idindex *truncindex.TruncIndex
|
||||||
byid map[string]*Container
|
byid map[string]*Container
|
||||||
bylayer map[string]*Container
|
bylayer map[string]*Container
|
||||||
@ -101,7 +101,11 @@ type containerStore struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *containerStore) Containers() ([]Container, error) {
|
func (r *containerStore) Containers() ([]Container, error) {
|
||||||
return r.containers, nil
|
containers := make([]Container, len(r.containers))
|
||||||
|
for i := range r.containers {
|
||||||
|
containers[i] = *(r.containers[i])
|
||||||
|
}
|
||||||
|
return containers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *containerStore) containerspath() string {
|
func (r *containerStore) containerspath() string {
|
||||||
@ -123,7 +127,7 @@ func (r *containerStore) Load() error {
|
|||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
containers := []Container{}
|
containers := []*Container{}
|
||||||
layers := make(map[string]*Container)
|
layers := make(map[string]*Container)
|
||||||
idlist := []string{}
|
idlist := []string{}
|
||||||
ids := make(map[string]*Container)
|
ids := make(map[string]*Container)
|
||||||
@ -131,14 +135,14 @@ func (r *containerStore) Load() error {
|
|||||||
if err = json.Unmarshal(data, &containers); len(data) == 0 || err == nil {
|
if err = json.Unmarshal(data, &containers); len(data) == 0 || err == nil {
|
||||||
for n, container := range containers {
|
for n, container := range containers {
|
||||||
idlist = append(idlist, container.ID)
|
idlist = append(idlist, container.ID)
|
||||||
ids[container.ID] = &containers[n]
|
ids[container.ID] = containers[n]
|
||||||
layers[container.LayerID] = &containers[n]
|
layers[container.LayerID] = containers[n]
|
||||||
for _, name := range container.Names {
|
for _, name := range container.Names {
|
||||||
if conflict, ok := names[name]; ok {
|
if conflict, ok := names[name]; ok {
|
||||||
r.removeName(conflict, name)
|
r.removeName(conflict, name)
|
||||||
needSave = true
|
needSave = true
|
||||||
}
|
}
|
||||||
names[name] = &containers[n]
|
names[name] = containers[n]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,7 +152,6 @@ func (r *containerStore) Load() error {
|
|||||||
r.bylayer = layers
|
r.bylayer = layers
|
||||||
r.byname = names
|
r.byname = names
|
||||||
if needSave {
|
if needSave {
|
||||||
r.Touch()
|
|
||||||
return r.Save()
|
return r.Save()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -163,6 +166,7 @@ func (r *containerStore) Save() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer r.Touch()
|
||||||
return ioutils.AtomicWriteFile(rpath, jdata, 0600)
|
return ioutils.AtomicWriteFile(rpath, jdata, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +183,7 @@ func newContainerStore(dir string) (ContainerStore, error) {
|
|||||||
cstore := containerStore{
|
cstore := containerStore{
|
||||||
lockfile: lockfile,
|
lockfile: lockfile,
|
||||||
dir: dir,
|
dir: dir,
|
||||||
containers: []Container{},
|
containers: []*Container{},
|
||||||
byid: make(map[string]*Container),
|
byid: make(map[string]*Container),
|
||||||
bylayer: make(map[string]*Container),
|
bylayer: make(map[string]*Container),
|
||||||
byname: make(map[string]*Container),
|
byname: make(map[string]*Container),
|
||||||
@ -241,7 +245,7 @@ func (r *containerStore) Create(id string, names []string, image, layer, metadat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
newContainer := Container{
|
container = &Container{
|
||||||
ID: id,
|
ID: id,
|
||||||
Names: names,
|
Names: names,
|
||||||
ImageID: image,
|
ImageID: image,
|
||||||
@ -251,8 +255,7 @@ func (r *containerStore) Create(id string, names []string, image, layer, metadat
|
|||||||
BigDataSizes: make(map[string]int64),
|
BigDataSizes: make(map[string]int64),
|
||||||
Flags: make(map[string]interface{}),
|
Flags: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
r.containers = append(r.containers, newContainer)
|
r.containers = append(r.containers, container)
|
||||||
container = &r.containers[len(r.containers)-1]
|
|
||||||
r.byid[id] = container
|
r.byid[id] = container
|
||||||
r.idindex.Add(id)
|
r.idindex.Add(id)
|
||||||
r.bylayer[layer] = container
|
r.bylayer[layer] = container
|
||||||
@ -306,7 +309,7 @@ func (r *containerStore) Delete(id string) error {
|
|||||||
return ErrContainerUnknown
|
return ErrContainerUnknown
|
||||||
}
|
}
|
||||||
id = container.ID
|
id = container.ID
|
||||||
newContainers := []Container{}
|
newContainers := []*Container{}
|
||||||
for _, candidate := range r.containers {
|
for _, candidate := range r.containers {
|
||||||
if candidate.ID != id {
|
if candidate.ID != id {
|
||||||
newContainers = append(newContainers, candidate)
|
newContainers = append(newContainers, candidate)
|
||||||
@ -437,6 +440,10 @@ func (r *containerStore) Modified() (bool, error) {
|
|||||||
return r.lockfile.Modified()
|
return r.lockfile.Modified()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *containerStore) IsReadWrite() bool {
|
||||||
|
return r.lockfile.IsReadWrite()
|
||||||
|
}
|
||||||
|
|
||||||
func (r *containerStore) TouchedSince(when time.Time) bool {
|
func (r *containerStore) TouchedSince(when time.Time) bool {
|
||||||
return r.lockfile.TouchedSince(when)
|
return r.lockfile.TouchedSince(when)
|
||||||
}
|
}
|
||||||
|
23
vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
generated
vendored
23
vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
generated
vendored
@ -28,7 +28,6 @@ import (
|
|||||||
"github.com/containers/storage/pkg/loopback"
|
"github.com/containers/storage/pkg/loopback"
|
||||||
"github.com/containers/storage/pkg/mount"
|
"github.com/containers/storage/pkg/mount"
|
||||||
"github.com/containers/storage/pkg/parsers"
|
"github.com/containers/storage/pkg/parsers"
|
||||||
"github.com/containers/storage/storageversion"
|
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
|
|
||||||
"github.com/opencontainers/selinux/go-selinux/label"
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
@ -1668,17 +1667,17 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/docker/docker/issues/4036
|
// https://github.com/docker/docker/issues/4036
|
||||||
if supported := devicemapper.UdevSetSyncSupport(true); !supported {
|
// if supported := devicemapper.UdevSetSyncSupport(true); !supported {
|
||||||
if storageversion.IAmStatic == "true" {
|
// if storageversion.IAmStatic == "true" {
|
||||||
logrus.Errorf("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a dynamic binary to use devicemapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/daemon/#daemon-storage-driver-option")
|
// logrus.Errorf("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a dynamic binary to use devicemapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/daemon/#daemon-storage-driver-option")
|
||||||
} else {
|
// } else {
|
||||||
logrus.Errorf("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a more recent version of libdevmapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/daemon/#daemon-storage-driver-option")
|
// logrus.Errorf("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a more recent version of libdevmapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/daemon/#daemon-storage-driver-option")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if !devices.overrideUdevSyncCheck {
|
// if !devices.overrideUdevSyncCheck {
|
||||||
return graphdriver.ErrNotSupported
|
// return graphdriver.ErrNotSupported
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
//create the root dir of the devmapper driver ownership to match this
|
//create the root dir of the devmapper driver ownership to match this
|
||||||
//daemon's remapped root uid/gid so containers can start properly
|
//daemon's remapped root uid/gid so containers can start properly
|
||||||
|
46
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
46
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
@ -377,8 +377,18 @@ func (d *Driver) getLower(parent string) (string, error) {
|
|||||||
return strings.Join(lowers, ":"), nil
|
return strings.Join(lowers, ":"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) dir(id string) string {
|
func (d *Driver) dir(val string) string {
|
||||||
return path.Join(d.home, id)
|
newpath := path.Join(d.home, val)
|
||||||
|
if _, err := os.Stat(newpath); err != nil {
|
||||||
|
for _, p := range d.AdditionalImageStores() {
|
||||||
|
l := path.Join(p, d.name, val)
|
||||||
|
_, err = os.Stat(l)
|
||||||
|
if err == nil {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newpath
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) getLowerDirs(id string) ([]string, error) {
|
func (d *Driver) getLowerDirs(id string) ([]string, error) {
|
||||||
@ -386,11 +396,12 @@ func (d *Driver) getLowerDirs(id string) ([]string, error) {
|
|||||||
lowers, err := ioutil.ReadFile(path.Join(d.dir(id), lowerFile))
|
lowers, err := ioutil.ReadFile(path.Join(d.dir(id), lowerFile))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
for _, s := range strings.Split(string(lowers), ":") {
|
for _, s := range strings.Split(string(lowers), ":") {
|
||||||
lp, err := os.Readlink(path.Join(d.home, s))
|
lower := d.dir(s)
|
||||||
|
lp, err := os.Readlink(lower)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
lowersArray = append(lowersArray, path.Clean(path.Join(d.home, "link", lp)))
|
lowersArray = append(lowersArray, path.Clean(d.dir(path.Join("link", lp))))
|
||||||
}
|
}
|
||||||
} else if !os.IsNotExist(err) {
|
} else if !os.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -431,6 +442,31 @@ func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newlowers := ""
|
||||||
|
for _, l := range strings.Split(string(lowers), ":") {
|
||||||
|
lower := ""
|
||||||
|
newpath := path.Join(d.home, l)
|
||||||
|
if _, err := os.Stat(newpath); err != nil {
|
||||||
|
for _, p := range d.AdditionalImageStores() {
|
||||||
|
lower = path.Join(p, d.name, l)
|
||||||
|
if _, err2 := os.Stat(lower); err2 == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
lower = ""
|
||||||
|
}
|
||||||
|
if lower == "" {
|
||||||
|
return "", fmt.Errorf("Can't stat lower layer %q: %v", newpath, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lower = l
|
||||||
|
}
|
||||||
|
if newlowers == "" {
|
||||||
|
newlowers = lower
|
||||||
|
} else {
|
||||||
|
newlowers = newlowers + ":" + lower
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mergedDir := path.Join(dir, "merged")
|
mergedDir := path.Join(dir, "merged")
|
||||||
if count := d.ctr.Increment(mergedDir); count > 1 {
|
if count := d.ctr.Increment(mergedDir); count > 1 {
|
||||||
return mergedDir, nil
|
return mergedDir, nil
|
||||||
@ -444,7 +480,7 @@ func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
workDir := path.Join(dir, "work")
|
workDir := path.Join(dir, "work")
|
||||||
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work"))
|
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", newlowers, path.Join(id, "diff"), path.Join(id, "work"))
|
||||||
mountLabel = label.FormatMountLabel(opts, mountLabel)
|
mountLabel = label.FormatMountLabel(opts, mountLabel)
|
||||||
if len(mountLabel) > syscall.Getpagesize() {
|
if len(mountLabel) > syscall.Getpagesize() {
|
||||||
return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountLabel))
|
return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountLabel))
|
||||||
|
127
vendor/github.com/containers/storage/images.go
generated
vendored
127
vendor/github.com/containers/storage/images.go
generated
vendored
@ -2,7 +2,6 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -11,6 +10,7 @@ import (
|
|||||||
"github.com/containers/storage/pkg/ioutils"
|
"github.com/containers/storage/pkg/ioutils"
|
||||||
"github.com/containers/storage/pkg/stringid"
|
"github.com/containers/storage/pkg/stringid"
|
||||||
"github.com/containers/storage/pkg/truncindex"
|
"github.com/containers/storage/pkg/truncindex"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -49,11 +49,32 @@ type Image struct {
|
|||||||
Flags map[string]interface{} `json:"flags,omitempty"`
|
Flags map[string]interface{} `json:"flags,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ROImageStore provides bookkeeping for information about Images.
|
||||||
|
type ROImageStore interface {
|
||||||
|
ROFileBasedStore
|
||||||
|
ROMetadataStore
|
||||||
|
ROBigDataStore
|
||||||
|
|
||||||
|
// Exists checks if there is an image with the given ID or name.
|
||||||
|
Exists(id string) bool
|
||||||
|
|
||||||
|
// Get retrieves information about an image given an ID or name.
|
||||||
|
Get(id string) (*Image, error)
|
||||||
|
|
||||||
|
// Lookup attempts to translate a name to an ID. Most methods do this
|
||||||
|
// implicitly.
|
||||||
|
Lookup(name string) (string, error)
|
||||||
|
|
||||||
|
// Images returns a slice enumerating the known images.
|
||||||
|
Images() ([]Image, error)
|
||||||
|
}
|
||||||
|
|
||||||
// ImageStore provides bookkeeping for information about Images.
|
// ImageStore provides bookkeeping for information about Images.
|
||||||
type ImageStore interface {
|
type ImageStore interface {
|
||||||
FileBasedStore
|
ROImageStore
|
||||||
MetadataStore
|
RWFileBasedStore
|
||||||
BigDataStore
|
RWMetadataStore
|
||||||
|
RWBigDataStore
|
||||||
FlaggableStore
|
FlaggableStore
|
||||||
|
|
||||||
// Create creates an image that has a specified ID (or a random one) and
|
// Create creates an image that has a specified ID (or a random one) and
|
||||||
@ -65,37 +86,28 @@ type ImageStore interface {
|
|||||||
// supplied values.
|
// supplied values.
|
||||||
SetNames(id string, names []string) error
|
SetNames(id string, names []string) error
|
||||||
|
|
||||||
// Exists checks if there is an image with the given ID or name.
|
|
||||||
Exists(id string) bool
|
|
||||||
|
|
||||||
// Get retrieves information about an image given an ID or name.
|
|
||||||
Get(id string) (*Image, error)
|
|
||||||
|
|
||||||
// Delete removes the record of the image.
|
// Delete removes the record of the image.
|
||||||
Delete(id string) error
|
Delete(id string) error
|
||||||
|
|
||||||
// Wipe removes records of all images.
|
// Wipe removes records of all images.
|
||||||
Wipe() error
|
Wipe() error
|
||||||
|
|
||||||
// Lookup attempts to translate a name to an ID. Most methods do this
|
|
||||||
// implicitly.
|
|
||||||
Lookup(name string) (string, error)
|
|
||||||
|
|
||||||
// Images returns a slice enumerating the known images.
|
|
||||||
Images() ([]Image, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type imageStore struct {
|
type imageStore struct {
|
||||||
lockfile Locker
|
lockfile Locker
|
||||||
dir string
|
dir string
|
||||||
images []Image
|
images []*Image
|
||||||
idindex *truncindex.TruncIndex
|
idindex *truncindex.TruncIndex
|
||||||
byid map[string]*Image
|
byid map[string]*Image
|
||||||
byname map[string]*Image
|
byname map[string]*Image
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) Images() ([]Image, error) {
|
func (r *imageStore) Images() ([]Image, error) {
|
||||||
return r.images, nil
|
images := make([]Image, len(r.images))
|
||||||
|
for i := range r.images {
|
||||||
|
images[i] = *(r.images[i])
|
||||||
|
}
|
||||||
|
return images, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) imagespath() string {
|
func (r *imageStore) imagespath() string {
|
||||||
@ -111,41 +123,46 @@ func (r *imageStore) datapath(id, key string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) Load() error {
|
func (r *imageStore) Load() error {
|
||||||
needSave := false
|
shouldSave := false
|
||||||
rpath := r.imagespath()
|
rpath := r.imagespath()
|
||||||
data, err := ioutil.ReadFile(rpath)
|
data, err := ioutil.ReadFile(rpath)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
images := []Image{}
|
images := []*Image{}
|
||||||
idlist := []string{}
|
idlist := []string{}
|
||||||
ids := make(map[string]*Image)
|
ids := make(map[string]*Image)
|
||||||
names := make(map[string]*Image)
|
names := make(map[string]*Image)
|
||||||
if err = json.Unmarshal(data, &images); len(data) == 0 || err == nil {
|
if err = json.Unmarshal(data, &images); len(data) == 0 || err == nil {
|
||||||
for n, image := range images {
|
for n, image := range images {
|
||||||
ids[image.ID] = &images[n]
|
ids[image.ID] = images[n]
|
||||||
idlist = append(idlist, image.ID)
|
idlist = append(idlist, image.ID)
|
||||||
for _, name := range image.Names {
|
for _, name := range image.Names {
|
||||||
if conflict, ok := names[name]; ok {
|
if conflict, ok := names[name]; ok {
|
||||||
r.removeName(conflict, name)
|
r.removeName(conflict, name)
|
||||||
needSave = true
|
shouldSave = true
|
||||||
}
|
}
|
||||||
names[name] = &images[n]
|
names[name] = images[n]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if shouldSave && !r.IsReadWrite() {
|
||||||
|
return errors.New("image store assigns the same name to multiple images")
|
||||||
|
}
|
||||||
r.images = images
|
r.images = images
|
||||||
r.idindex = truncindex.NewTruncIndex(idlist)
|
r.idindex = truncindex.NewTruncIndex(idlist)
|
||||||
r.byid = ids
|
r.byid = ids
|
||||||
r.byname = names
|
r.byname = names
|
||||||
if needSave {
|
if shouldSave {
|
||||||
r.Touch()
|
|
||||||
return r.Save()
|
return r.Save()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) Save() error {
|
func (r *imageStore) Save() error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify the image store at %q", r.imagespath())
|
||||||
|
}
|
||||||
rpath := r.imagespath()
|
rpath := r.imagespath()
|
||||||
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil {
|
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -154,6 +171,7 @@ func (r *imageStore) Save() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer r.Touch()
|
||||||
return ioutils.AtomicWriteFile(rpath, jdata, 0600)
|
return ioutils.AtomicWriteFile(rpath, jdata, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +188,27 @@ func newImageStore(dir string) (ImageStore, error) {
|
|||||||
istore := imageStore{
|
istore := imageStore{
|
||||||
lockfile: lockfile,
|
lockfile: lockfile,
|
||||||
dir: dir,
|
dir: dir,
|
||||||
images: []Image{},
|
images: []*Image{},
|
||||||
|
byid: make(map[string]*Image),
|
||||||
|
byname: make(map[string]*Image),
|
||||||
|
}
|
||||||
|
if err := istore.Load(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &istore, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newROImageStore(dir string) (ROImageStore, error) {
|
||||||
|
lockfile, err := GetROLockfile(filepath.Join(dir, "images.lock"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
lockfile.Lock()
|
||||||
|
defer lockfile.Unlock()
|
||||||
|
istore := imageStore{
|
||||||
|
lockfile: lockfile,
|
||||||
|
dir: dir,
|
||||||
|
images: []*Image{},
|
||||||
byid: make(map[string]*Image),
|
byid: make(map[string]*Image),
|
||||||
byname: make(map[string]*Image),
|
byname: make(map[string]*Image),
|
||||||
}
|
}
|
||||||
@ -193,6 +231,9 @@ func (r *imageStore) lookup(id string) (*Image, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) ClearFlag(id string, flag string) error {
|
func (r *imageStore) ClearFlag(id string, flag string) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to clear flags on images at %q", r.imagespath())
|
||||||
|
}
|
||||||
image, ok := r.lookup(id)
|
image, ok := r.lookup(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrImageUnknown
|
return ErrImageUnknown
|
||||||
@ -202,6 +243,9 @@ func (r *imageStore) ClearFlag(id string, flag string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) SetFlag(id string, flag string, value interface{}) error {
|
func (r *imageStore) SetFlag(id string, flag string, value interface{}) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to set flags on images at %q", r.imagespath())
|
||||||
|
}
|
||||||
image, ok := r.lookup(id)
|
image, ok := r.lookup(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrImageUnknown
|
return ErrImageUnknown
|
||||||
@ -211,6 +255,9 @@ func (r *imageStore) SetFlag(id string, flag string, value interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) Create(id string, names []string, layer, metadata string) (image *Image, err error) {
|
func (r *imageStore) Create(id string, names []string, layer, metadata string) (image *Image, err error) {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return nil, errors.Wrapf(ErrStoreIsReadOnly, "not allowed to create new images at %q", r.imagespath())
|
||||||
|
}
|
||||||
if id == "" {
|
if id == "" {
|
||||||
id = stringid.GenerateRandomID()
|
id = stringid.GenerateRandomID()
|
||||||
_, idInUse := r.byid[id]
|
_, idInUse := r.byid[id]
|
||||||
@ -228,7 +275,7 @@ func (r *imageStore) Create(id string, names []string, layer, metadata string) (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
newImage := Image{
|
image = &Image{
|
||||||
ID: id,
|
ID: id,
|
||||||
Names: names,
|
Names: names,
|
||||||
TopLayer: layer,
|
TopLayer: layer,
|
||||||
@ -237,8 +284,7 @@ func (r *imageStore) Create(id string, names []string, layer, metadata string) (
|
|||||||
BigDataSizes: make(map[string]int64),
|
BigDataSizes: make(map[string]int64),
|
||||||
Flags: make(map[string]interface{}),
|
Flags: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
r.images = append(r.images, newImage)
|
r.images = append(r.images, image)
|
||||||
image = &r.images[len(r.images)-1]
|
|
||||||
r.idindex.Add(id)
|
r.idindex.Add(id)
|
||||||
r.byid[id] = image
|
r.byid[id] = image
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
@ -257,6 +303,9 @@ func (r *imageStore) Metadata(id string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) SetMetadata(id, metadata string) error {
|
func (r *imageStore) SetMetadata(id, metadata string) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify image metadata at %q", r.imagespath())
|
||||||
|
}
|
||||||
if image, ok := r.lookup(id); ok {
|
if image, ok := r.lookup(id); ok {
|
||||||
image.Metadata = metadata
|
image.Metadata = metadata
|
||||||
return r.Save()
|
return r.Save()
|
||||||
@ -269,6 +318,9 @@ func (r *imageStore) removeName(image *Image, name string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) SetNames(id string, names []string) error {
|
func (r *imageStore) SetNames(id string, names []string) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to change image name assignments at %q", r.imagespath())
|
||||||
|
}
|
||||||
if image, ok := r.lookup(id); ok {
|
if image, ok := r.lookup(id); ok {
|
||||||
for _, name := range image.Names {
|
for _, name := range image.Names {
|
||||||
delete(r.byname, name)
|
delete(r.byname, name)
|
||||||
@ -286,12 +338,15 @@ func (r *imageStore) SetNames(id string, names []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) Delete(id string) error {
|
func (r *imageStore) Delete(id string) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to delete images at %q", r.imagespath())
|
||||||
|
}
|
||||||
image, ok := r.lookup(id)
|
image, ok := r.lookup(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrImageUnknown
|
return ErrImageUnknown
|
||||||
}
|
}
|
||||||
id = image.ID
|
id = image.ID
|
||||||
newImages := []Image{}
|
newImages := []*Image{}
|
||||||
for _, candidate := range r.images {
|
for _, candidate := range r.images {
|
||||||
if candidate.ID != id {
|
if candidate.ID != id {
|
||||||
newImages = append(newImages, candidate)
|
newImages = append(newImages, candidate)
|
||||||
@ -359,6 +414,9 @@ func (r *imageStore) BigDataNames(id string) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) SetBigData(id, key string, data []byte) error {
|
func (r *imageStore) SetBigData(id, key string, data []byte) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to save data items associated with images at %q", r.imagespath())
|
||||||
|
}
|
||||||
image, ok := r.lookup(id)
|
image, ok := r.lookup(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrImageUnknown
|
return ErrImageUnknown
|
||||||
@ -393,6 +451,9 @@ func (r *imageStore) SetBigData(id, key string, data []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) Wipe() error {
|
func (r *imageStore) Wipe() error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to delete images at %q", r.imagespath())
|
||||||
|
}
|
||||||
ids := []string{}
|
ids := []string{}
|
||||||
for id := range r.byid {
|
for id := range r.byid {
|
||||||
ids = append(ids, id)
|
ids = append(ids, id)
|
||||||
@ -421,6 +482,10 @@ func (r *imageStore) Modified() (bool, error) {
|
|||||||
return r.lockfile.Modified()
|
return r.lockfile.Modified()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *imageStore) IsReadWrite() bool {
|
||||||
|
return r.lockfile.IsReadWrite()
|
||||||
|
}
|
||||||
|
|
||||||
func (r *imageStore) TouchedSince(when time.Time) bool {
|
func (r *imageStore) TouchedSince(when time.Time) bool {
|
||||||
return r.lockfile.TouchedSince(when)
|
return r.lockfile.TouchedSince(when)
|
||||||
}
|
}
|
||||||
|
213
vendor/github.com/containers/storage/layers.go
generated
vendored
213
vendor/github.com/containers/storage/layers.go
generated
vendored
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@ -16,6 +15,7 @@ import (
|
|||||||
"github.com/containers/storage/pkg/ioutils"
|
"github.com/containers/storage/pkg/ioutils"
|
||||||
"github.com/containers/storage/pkg/stringid"
|
"github.com/containers/storage/pkg/stringid"
|
||||||
"github.com/containers/storage/pkg/truncindex"
|
"github.com/containers/storage/pkg/truncindex"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/vbatts/tar-split/tar/asm"
|
"github.com/vbatts/tar-split/tar/asm"
|
||||||
"github.com/vbatts/tar-split/tar/storage"
|
"github.com/vbatts/tar-split/tar/storage"
|
||||||
)
|
)
|
||||||
@ -75,28 +75,12 @@ type layerMountPoint struct {
|
|||||||
MountCount int `json:"count"`
|
MountCount int `json:"count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LayerStore wraps a graph driver, adding the ability to refer to layers by
|
// ROLayerStore wraps a graph driver, adding the ability to refer to layers by
|
||||||
// name, and keeping track of parent-child relationships, along with a list of
|
// name, and keeping track of parent-child relationships, along with a list of
|
||||||
// all known layers.
|
// all known layers.
|
||||||
type LayerStore interface {
|
type ROLayerStore interface {
|
||||||
FileBasedStore
|
ROFileBasedStore
|
||||||
MetadataStore
|
ROMetadataStore
|
||||||
FlaggableStore
|
|
||||||
|
|
||||||
// Create creates a new layer, optionally giving it a specified ID rather than
|
|
||||||
// a randomly-generated one, either inheriting data from another specified
|
|
||||||
// layer or the empty base layer. The new layer can optionally be given names
|
|
||||||
// and have an SELinux label specified for use when mounting it. Some
|
|
||||||
// underlying drivers can accept a "size" option. At this time, most
|
|
||||||
// underlying drivers do not themselves distinguish between writeable
|
|
||||||
// and read-only layers.
|
|
||||||
Create(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool) (*Layer, error)
|
|
||||||
|
|
||||||
// CreateWithFlags combines the functions of Create and SetFlag.
|
|
||||||
CreateWithFlags(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}) (layer *Layer, err error)
|
|
||||||
|
|
||||||
// Put combines the functions of CreateWithFlags and ApplyDiff.
|
|
||||||
Put(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}, diff archive.Reader) (*Layer, int64, error)
|
|
||||||
|
|
||||||
// Exists checks if a layer with the specified name or ID is known.
|
// Exists checks if a layer with the specified name or ID is known.
|
||||||
Exists(id string) bool
|
Exists(id string) bool
|
||||||
@ -104,28 +88,10 @@ type LayerStore interface {
|
|||||||
// Get retrieves information about a layer given an ID or name.
|
// Get retrieves information about a layer given an ID or name.
|
||||||
Get(id string) (*Layer, error)
|
Get(id string) (*Layer, error)
|
||||||
|
|
||||||
// SetNames replaces the list of names associated with a layer with the
|
|
||||||
// supplied values.
|
|
||||||
SetNames(id string, names []string) error
|
|
||||||
|
|
||||||
// Status returns an slice of key-value pairs, suitable for human consumption,
|
// Status returns an slice of key-value pairs, suitable for human consumption,
|
||||||
// relaying whatever status information the underlying driver can share.
|
// relaying whatever status information the underlying driver can share.
|
||||||
Status() ([][2]string, error)
|
Status() ([][2]string, error)
|
||||||
|
|
||||||
// Delete deletes a layer with the specified name or ID.
|
|
||||||
Delete(id string) error
|
|
||||||
|
|
||||||
// Wipe deletes all layers.
|
|
||||||
Wipe() error
|
|
||||||
|
|
||||||
// Mount mounts a layer for use. If the specified layer is the parent of other
|
|
||||||
// layers, it should not be written to. An SELinux label to be applied to the
|
|
||||||
// mount can be specified to override the one configured for the layer.
|
|
||||||
Mount(id, mountLabel string) (string, error)
|
|
||||||
|
|
||||||
// Unmount unmounts a layer when it is no longer in use.
|
|
||||||
Unmount(id string) error
|
|
||||||
|
|
||||||
// Changes returns a slice of Change structures, which contain a pathname
|
// Changes returns a slice of Change structures, which contain a pathname
|
||||||
// (Path) and a description of what sort of change (Kind) was made by the
|
// (Path) and a description of what sort of change (Kind) was made by the
|
||||||
// layer (either ChangeModify, ChangeAdd, or ChangeDelete), relative to a
|
// layer (either ChangeModify, ChangeAdd, or ChangeDelete), relative to a
|
||||||
@ -142,10 +108,6 @@ type LayerStore interface {
|
|||||||
// produced by Diff.
|
// produced by Diff.
|
||||||
DiffSize(from, to string) (int64, error)
|
DiffSize(from, to string) (int64, error)
|
||||||
|
|
||||||
// ApplyDiff reads a tarstream which was created by a previous call to Diff and
|
|
||||||
// applies its changes to a specified layer.
|
|
||||||
ApplyDiff(to string, diff archive.Reader) (int64, error)
|
|
||||||
|
|
||||||
// Lookup attempts to translate a name to an ID. Most methods do this
|
// Lookup attempts to translate a name to an ID. Most methods do this
|
||||||
// implicitly.
|
// implicitly.
|
||||||
Lookup(name string) (string, error)
|
Lookup(name string) (string, error)
|
||||||
@ -154,12 +116,59 @@ type LayerStore interface {
|
|||||||
Layers() ([]Layer, error)
|
Layers() ([]Layer, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LayerStore wraps a graph driver, adding the ability to refer to layers by
|
||||||
|
// name, and keeping track of parent-child relationships, along with a list of
|
||||||
|
// all known layers.
|
||||||
|
type LayerStore interface {
|
||||||
|
ROLayerStore
|
||||||
|
RWFileBasedStore
|
||||||
|
RWMetadataStore
|
||||||
|
FlaggableStore
|
||||||
|
|
||||||
|
// Create creates a new layer, optionally giving it a specified ID rather than
|
||||||
|
// a randomly-generated one, either inheriting data from another specified
|
||||||
|
// layer or the empty base layer. The new layer can optionally be given names
|
||||||
|
// and have an SELinux label specified for use when mounting it. Some
|
||||||
|
// underlying drivers can accept a "size" option. At this time, most
|
||||||
|
// underlying drivers do not themselves distinguish between writeable
|
||||||
|
// and read-only layers.
|
||||||
|
Create(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool) (*Layer, error)
|
||||||
|
|
||||||
|
// CreateWithFlags combines the functions of Create and SetFlag.
|
||||||
|
CreateWithFlags(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}) (layer *Layer, err error)
|
||||||
|
|
||||||
|
// Put combines the functions of CreateWithFlags and ApplyDiff.
|
||||||
|
Put(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}, diff archive.Reader) (*Layer, int64, error)
|
||||||
|
|
||||||
|
// SetNames replaces the list of names associated with a layer with the
|
||||||
|
// supplied values.
|
||||||
|
SetNames(id string, names []string) error
|
||||||
|
|
||||||
|
// Delete deletes a layer with the specified name or ID.
|
||||||
|
Delete(id string) error
|
||||||
|
|
||||||
|
// Wipe deletes all layers.
|
||||||
|
Wipe() error
|
||||||
|
|
||||||
|
// Mount mounts a layer for use. If the specified layer is the parent of other
|
||||||
|
// layers, it should not be written to. An SELinux label to be applied to the
|
||||||
|
// mount can be specified to override the one configured for the layer.
|
||||||
|
Mount(id, mountLabel string) (string, error)
|
||||||
|
|
||||||
|
// Unmount unmounts a layer when it is no longer in use.
|
||||||
|
Unmount(id string) error
|
||||||
|
|
||||||
|
// ApplyDiff reads a tarstream which was created by a previous call to Diff and
|
||||||
|
// applies its changes to a specified layer.
|
||||||
|
ApplyDiff(to string, diff archive.Reader) (int64, error)
|
||||||
|
}
|
||||||
|
|
||||||
type layerStore struct {
|
type layerStore struct {
|
||||||
lockfile Locker
|
lockfile Locker
|
||||||
rundir string
|
rundir string
|
||||||
driver drivers.Driver
|
driver drivers.Driver
|
||||||
layerdir string
|
layerdir string
|
||||||
layers []Layer
|
layers []*Layer
|
||||||
idindex *truncindex.TruncIndex
|
idindex *truncindex.TruncIndex
|
||||||
byid map[string]*Layer
|
byid map[string]*Layer
|
||||||
byname map[string]*Layer
|
byname map[string]*Layer
|
||||||
@ -167,7 +176,11 @@ type layerStore struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) Layers() ([]Layer, error) {
|
func (r *layerStore) Layers() ([]Layer, error) {
|
||||||
return r.layers, nil
|
layers := make([]Layer, len(r.layers))
|
||||||
|
for i := range r.layers {
|
||||||
|
layers[i] = *(r.layers[i])
|
||||||
|
}
|
||||||
|
return layers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) mountspath() string {
|
func (r *layerStore) mountspath() string {
|
||||||
@ -179,13 +192,13 @@ func (r *layerStore) layerspath() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) Load() error {
|
func (r *layerStore) Load() error {
|
||||||
needSave := false
|
shouldSave := false
|
||||||
rpath := r.layerspath()
|
rpath := r.layerspath()
|
||||||
data, err := ioutil.ReadFile(rpath)
|
data, err := ioutil.ReadFile(rpath)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
layers := []Layer{}
|
layers := []*Layer{}
|
||||||
idlist := []string{}
|
idlist := []string{}
|
||||||
ids := make(map[string]*Layer)
|
ids := make(map[string]*Layer)
|
||||||
names := make(map[string]*Layer)
|
names := make(map[string]*Layer)
|
||||||
@ -193,22 +206,25 @@ func (r *layerStore) Load() error {
|
|||||||
parents := make(map[string][]*Layer)
|
parents := make(map[string][]*Layer)
|
||||||
if err = json.Unmarshal(data, &layers); len(data) == 0 || err == nil {
|
if err = json.Unmarshal(data, &layers); len(data) == 0 || err == nil {
|
||||||
for n, layer := range layers {
|
for n, layer := range layers {
|
||||||
ids[layer.ID] = &layers[n]
|
ids[layer.ID] = layers[n]
|
||||||
idlist = append(idlist, layer.ID)
|
idlist = append(idlist, layer.ID)
|
||||||
for _, name := range layer.Names {
|
for _, name := range layer.Names {
|
||||||
if conflict, ok := names[name]; ok {
|
if conflict, ok := names[name]; ok {
|
||||||
r.removeName(conflict, name)
|
r.removeName(conflict, name)
|
||||||
needSave = true
|
shouldSave = true
|
||||||
}
|
}
|
||||||
names[name] = &layers[n]
|
names[name] = layers[n]
|
||||||
}
|
}
|
||||||
if pslice, ok := parents[layer.Parent]; ok {
|
if pslice, ok := parents[layer.Parent]; ok {
|
||||||
parents[layer.Parent] = append(pslice, &layers[n])
|
parents[layer.Parent] = append(pslice, layers[n])
|
||||||
} else {
|
} else {
|
||||||
parents[layer.Parent] = []*Layer{&layers[n]}
|
parents[layer.Parent] = []*Layer{layers[n]}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if shouldSave && !r.IsReadWrite() {
|
||||||
|
return errors.New("layer store assigns the same name to multiple layers")
|
||||||
|
}
|
||||||
mpath := r.mountspath()
|
mpath := r.mountspath()
|
||||||
data, err = ioutil.ReadFile(mpath)
|
data, err = ioutil.ReadFile(mpath)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
@ -232,28 +248,32 @@ func (r *layerStore) Load() error {
|
|||||||
r.byname = names
|
r.byname = names
|
||||||
r.bymount = mounts
|
r.bymount = mounts
|
||||||
err = nil
|
err = nil
|
||||||
// Last step: try to remove anything that a previous user of this
|
// Last step: if we're writable, try to remove anything that a previous
|
||||||
// storage area marked for deletion but didn't manage to actually
|
// user of this storage area marked for deletion but didn't manage to
|
||||||
// delete.
|
// actually delete.
|
||||||
for _, layer := range r.layers {
|
if r.IsReadWrite() {
|
||||||
if cleanup, ok := layer.Flags[incompleteFlag]; ok {
|
for _, layer := range r.layers {
|
||||||
if b, ok := cleanup.(bool); ok && b {
|
if cleanup, ok := layer.Flags[incompleteFlag]; ok {
|
||||||
err = r.Delete(layer.ID)
|
if b, ok := cleanup.(bool); ok && b {
|
||||||
if err != nil {
|
err = r.Delete(layer.ID)
|
||||||
break
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
shouldSave = true
|
||||||
}
|
}
|
||||||
needSave = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if shouldSave {
|
||||||
if needSave {
|
return r.Save()
|
||||||
r.Touch()
|
}
|
||||||
return r.Save()
|
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) Save() error {
|
func (r *layerStore) Save() error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify the layer store at %q", r.layerspath())
|
||||||
|
}
|
||||||
rpath := r.layerspath()
|
rpath := r.layerspath()
|
||||||
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil {
|
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -283,6 +303,7 @@ func (r *layerStore) Save() error {
|
|||||||
if err := ioutils.AtomicWriteFile(rpath, jldata, 0600); err != nil {
|
if err := ioutils.AtomicWriteFile(rpath, jldata, 0600); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer r.Touch()
|
||||||
return ioutils.AtomicWriteFile(mpath, jmdata, 0600)
|
return ioutils.AtomicWriteFile(mpath, jmdata, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,6 +335,28 @@ func newLayerStore(rundir string, layerdir string, driver drivers.Driver) (Layer
|
|||||||
return &rlstore, nil
|
return &rlstore, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newROLayerStore(rundir string, layerdir string, driver drivers.Driver) (ROLayerStore, error) {
|
||||||
|
lockfile, err := GetROLockfile(filepath.Join(layerdir, "layers.lock"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
lockfile.Lock()
|
||||||
|
defer lockfile.Unlock()
|
||||||
|
rlstore := layerStore{
|
||||||
|
lockfile: lockfile,
|
||||||
|
driver: driver,
|
||||||
|
rundir: rundir,
|
||||||
|
layerdir: layerdir,
|
||||||
|
byid: make(map[string]*Layer),
|
||||||
|
bymount: make(map[string]*Layer),
|
||||||
|
byname: make(map[string]*Layer),
|
||||||
|
}
|
||||||
|
if err := rlstore.Load(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &rlstore, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *layerStore) lookup(id string) (*Layer, bool) {
|
func (r *layerStore) lookup(id string) (*Layer, bool) {
|
||||||
if layer, ok := r.byid[id]; ok {
|
if layer, ok := r.byid[id]; ok {
|
||||||
return layer, ok
|
return layer, ok
|
||||||
@ -327,6 +370,9 @@ func (r *layerStore) lookup(id string) (*Layer, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) ClearFlag(id string, flag string) error {
|
func (r *layerStore) ClearFlag(id string, flag string) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to clear flags on layers at %q", r.layerspath())
|
||||||
|
}
|
||||||
layer, ok := r.lookup(id)
|
layer, ok := r.lookup(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrLayerUnknown
|
return ErrLayerUnknown
|
||||||
@ -336,6 +382,9 @@ func (r *layerStore) ClearFlag(id string, flag string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) SetFlag(id string, flag string, value interface{}) error {
|
func (r *layerStore) SetFlag(id string, flag string, value interface{}) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to set flags on layers at %q", r.layerspath())
|
||||||
|
}
|
||||||
layer, ok := r.lookup(id)
|
layer, ok := r.lookup(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrLayerUnknown
|
return ErrLayerUnknown
|
||||||
@ -349,6 +398,9 @@ func (r *layerStore) Status() ([][2]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) Put(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}, diff archive.Reader) (layer *Layer, size int64, err error) {
|
func (r *layerStore) Put(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}, diff archive.Reader) (layer *Layer, size int64, err error) {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return nil, -1, errors.Wrapf(ErrStoreIsReadOnly, "not allowed to create new layers at %q", r.layerspath())
|
||||||
|
}
|
||||||
size = -1
|
size = -1
|
||||||
if err := os.MkdirAll(r.rundir, 0700); err != nil {
|
if err := os.MkdirAll(r.rundir, 0700); err != nil {
|
||||||
return nil, -1, err
|
return nil, -1, err
|
||||||
@ -383,15 +435,14 @@ func (r *layerStore) Put(id, parent string, names []string, mountLabel string, o
|
|||||||
err = r.driver.Create(id, parent, mountLabel, options)
|
err = r.driver.Create(id, parent, mountLabel, options)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
newLayer := Layer{
|
layer = &Layer{
|
||||||
ID: id,
|
ID: id,
|
||||||
Parent: parent,
|
Parent: parent,
|
||||||
Names: names,
|
Names: names,
|
||||||
MountLabel: mountLabel,
|
MountLabel: mountLabel,
|
||||||
Flags: make(map[string]interface{}),
|
Flags: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
r.layers = append(r.layers, newLayer)
|
r.layers = append(r.layers, layer)
|
||||||
layer = &r.layers[len(r.layers)-1]
|
|
||||||
r.idindex.Add(id)
|
r.idindex.Add(id)
|
||||||
r.byid[id] = layer
|
r.byid[id] = layer
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
@ -441,6 +492,9 @@ func (r *layerStore) Create(id, parent string, names []string, mountLabel string
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) Mount(id, mountLabel string) (string, error) {
|
func (r *layerStore) Mount(id, mountLabel string) (string, error) {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return "", errors.Wrapf(ErrStoreIsReadOnly, "not allowed to update mount locations for layers at %q", r.mountspath())
|
||||||
|
}
|
||||||
layer, ok := r.lookup(id)
|
layer, ok := r.lookup(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", ErrLayerUnknown
|
return "", ErrLayerUnknown
|
||||||
@ -466,6 +520,9 @@ func (r *layerStore) Mount(id, mountLabel string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) Unmount(id string) error {
|
func (r *layerStore) Unmount(id string) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to update mount locations for layers at %q", r.mountspath())
|
||||||
|
}
|
||||||
layer, ok := r.lookup(id)
|
layer, ok := r.lookup(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
layerByMount, ok := r.bymount[filepath.Clean(id)]
|
layerByMount, ok := r.bymount[filepath.Clean(id)]
|
||||||
@ -495,6 +552,9 @@ func (r *layerStore) removeName(layer *Layer, name string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) SetNames(id string, names []string) error {
|
func (r *layerStore) SetNames(id string, names []string) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to change layer name assignments at %q", r.layerspath())
|
||||||
|
}
|
||||||
if layer, ok := r.lookup(id); ok {
|
if layer, ok := r.lookup(id); ok {
|
||||||
for _, name := range layer.Names {
|
for _, name := range layer.Names {
|
||||||
delete(r.byname, name)
|
delete(r.byname, name)
|
||||||
@ -519,6 +579,9 @@ func (r *layerStore) Metadata(id string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) SetMetadata(id, metadata string) error {
|
func (r *layerStore) SetMetadata(id, metadata string) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify layer metadata at %q", r.layerspath())
|
||||||
|
}
|
||||||
if layer, ok := r.lookup(id); ok {
|
if layer, ok := r.lookup(id); ok {
|
||||||
layer.Metadata = metadata
|
layer.Metadata = metadata
|
||||||
return r.Save()
|
return r.Save()
|
||||||
@ -531,6 +594,9 @@ func (r *layerStore) tspath(id string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) Delete(id string) error {
|
func (r *layerStore) Delete(id string) error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to delete layers at %q", r.layerspath())
|
||||||
|
}
|
||||||
layer, ok := r.lookup(id)
|
layer, ok := r.lookup(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrLayerUnknown
|
return ErrLayerUnknown
|
||||||
@ -549,7 +615,7 @@ func (r *layerStore) Delete(id string) error {
|
|||||||
if layer.MountPoint != "" {
|
if layer.MountPoint != "" {
|
||||||
delete(r.bymount, layer.MountPoint)
|
delete(r.bymount, layer.MountPoint)
|
||||||
}
|
}
|
||||||
newLayers := []Layer{}
|
newLayers := []*Layer{}
|
||||||
for _, candidate := range r.layers {
|
for _, candidate := range r.layers {
|
||||||
if candidate.ID != id {
|
if candidate.ID != id {
|
||||||
newLayers = append(newLayers, candidate)
|
newLayers = append(newLayers, candidate)
|
||||||
@ -583,6 +649,9 @@ func (r *layerStore) Get(id string) (*Layer, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) Wipe() error {
|
func (r *layerStore) Wipe() error {
|
||||||
|
if !r.IsReadWrite() {
|
||||||
|
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to delete layers at %q", r.layerspath())
|
||||||
|
}
|
||||||
ids := []string{}
|
ids := []string{}
|
||||||
for id := range r.byid {
|
for id := range r.byid {
|
||||||
ids = append(ids, id)
|
ids = append(ids, id)
|
||||||
@ -822,6 +891,10 @@ func (r *layerStore) Modified() (bool, error) {
|
|||||||
return r.lockfile.Modified()
|
return r.lockfile.Modified()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *layerStore) IsReadWrite() bool {
|
||||||
|
return r.lockfile.IsReadWrite()
|
||||||
|
}
|
||||||
|
|
||||||
func (r *layerStore) TouchedSince(when time.Time) bool {
|
func (r *layerStore) TouchedSince(when time.Time) bool {
|
||||||
return r.lockfile.TouchedSince(when)
|
return r.lockfile.TouchedSince(when)
|
||||||
}
|
}
|
||||||
|
73
vendor/github.com/containers/storage/lockfile.go
generated
vendored
73
vendor/github.com/containers/storage/lockfile.go
generated
vendored
@ -1,14 +1,15 @@
|
|||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
"github.com/containers/storage/pkg/stringid"
|
"github.com/containers/storage/pkg/stringid"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Locker represents a file lock where the file is used to cache an
|
// A Locker represents a file lock where the file is used to cache an
|
||||||
@ -27,43 +28,80 @@ type Locker interface {
|
|||||||
|
|
||||||
// TouchedSince() checks if the most recent writer modified the file (likely using Touch()) after the specified time.
|
// TouchedSince() checks if the most recent writer modified the file (likely using Touch()) after the specified time.
|
||||||
TouchedSince(when time.Time) bool
|
TouchedSince(when time.Time) bool
|
||||||
|
|
||||||
|
// IsReadWrite() checks if the lock file is read-write
|
||||||
|
IsReadWrite() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type lockfile struct {
|
type lockfile struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
file string
|
file string
|
||||||
fd uintptr
|
fd uintptr
|
||||||
lw string
|
lw string
|
||||||
|
locktype int16
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
lockfiles map[string]*lockfile
|
lockfiles map[string]*lockfile
|
||||||
lockfilesLock sync.Mutex
|
lockfilesLock sync.Mutex
|
||||||
|
// ErrLockReadOnly indicates that the caller only took a read-only lock, and is not allowed to write
|
||||||
|
ErrLockReadOnly = errors.New("lock is not a read-write lock")
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetLockfile opens a lock file, creating it if necessary. The Locker object
|
// GetLockfile opens a read-write lock file, creating it if necessary. The
|
||||||
// return will be returned unlocked.
|
// Locker object it returns will be returned unlocked.
|
||||||
func GetLockfile(path string) (Locker, error) {
|
func GetLockfile(path string) (Locker, error) {
|
||||||
lockfilesLock.Lock()
|
lockfilesLock.Lock()
|
||||||
defer lockfilesLock.Unlock()
|
defer lockfilesLock.Unlock()
|
||||||
if lockfiles == nil {
|
if lockfiles == nil {
|
||||||
lockfiles = make(map[string]*lockfile)
|
lockfiles = make(map[string]*lockfile)
|
||||||
}
|
}
|
||||||
if locker, ok := lockfiles[filepath.Clean(path)]; ok {
|
cleanPath := filepath.Clean(path)
|
||||||
|
if locker, ok := lockfiles[cleanPath]; ok {
|
||||||
|
if !locker.IsReadWrite() {
|
||||||
|
return nil, errors.Wrapf(ErrLockReadOnly, "lock %q is a read-only lock", cleanPath)
|
||||||
|
}
|
||||||
return locker, nil
|
return locker, nil
|
||||||
}
|
}
|
||||||
fd, err := unix.Open(filepath.Clean(path), os.O_RDWR|os.O_CREATE, unix.S_IRUSR|unix.S_IWUSR)
|
fd, err := unix.Open(cleanPath, os.O_RDWR|os.O_CREATE, unix.S_IRUSR|unix.S_IWUSR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrapf(err, "error opening %q", cleanPath)
|
||||||
}
|
}
|
||||||
locker := &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID()}
|
unix.CloseOnExec(fd)
|
||||||
|
locker := &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_WRLCK}
|
||||||
lockfiles[filepath.Clean(path)] = locker
|
lockfiles[filepath.Clean(path)] = locker
|
||||||
return locker, nil
|
return locker, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetROLockfile opens a read-only lock file. The Locker object it returns
|
||||||
|
// will be returned unlocked.
|
||||||
|
func GetROLockfile(path string) (Locker, error) {
|
||||||
|
lockfilesLock.Lock()
|
||||||
|
defer lockfilesLock.Unlock()
|
||||||
|
if lockfiles == nil {
|
||||||
|
lockfiles = make(map[string]*lockfile)
|
||||||
|
}
|
||||||
|
cleanPath := filepath.Clean(path)
|
||||||
|
if locker, ok := lockfiles[cleanPath]; ok {
|
||||||
|
if locker.IsReadWrite() {
|
||||||
|
return nil, fmt.Errorf("lock %q is a read-write lock", cleanPath)
|
||||||
|
}
|
||||||
|
return locker, nil
|
||||||
|
}
|
||||||
|
fd, err := unix.Open(cleanPath, os.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error opening %q", cleanPath)
|
||||||
|
}
|
||||||
|
unix.CloseOnExec(fd)
|
||||||
|
locker := &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_RDLCK}
|
||||||
|
lockfiles[filepath.Clean(path)] = locker
|
||||||
|
return locker, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock locks the lock file
|
||||||
func (l *lockfile) Lock() {
|
func (l *lockfile) Lock() {
|
||||||
lk := unix.Flock_t{
|
lk := unix.Flock_t{
|
||||||
Type: unix.F_WRLCK,
|
Type: l.locktype,
|
||||||
Whence: int16(os.SEEK_SET),
|
Whence: int16(os.SEEK_SET),
|
||||||
Start: 0,
|
Start: 0,
|
||||||
Len: 0,
|
Len: 0,
|
||||||
@ -75,6 +113,7 @@ func (l *lockfile) Lock() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unlock unlocks the lock file
|
||||||
func (l *lockfile) Unlock() {
|
func (l *lockfile) Unlock() {
|
||||||
lk := unix.Flock_t{
|
lk := unix.Flock_t{
|
||||||
Type: unix.F_UNLCK,
|
Type: unix.F_UNLCK,
|
||||||
@ -89,6 +128,7 @@ func (l *lockfile) Unlock() {
|
|||||||
l.mu.Unlock()
|
l.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Touch updates the lock file with the UID of the user
|
||||||
func (l *lockfile) Touch() error {
|
func (l *lockfile) Touch() error {
|
||||||
l.lw = stringid.GenerateRandomID()
|
l.lw = stringid.GenerateRandomID()
|
||||||
id := []byte(l.lw)
|
id := []byte(l.lw)
|
||||||
@ -110,6 +150,7 @@ func (l *lockfile) Touch() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Modified indicates if the lock file has been updated since the last time it was loaded
|
||||||
func (l *lockfile) Modified() (bool, error) {
|
func (l *lockfile) Modified() (bool, error) {
|
||||||
id := []byte(l.lw)
|
id := []byte(l.lw)
|
||||||
_, err := unix.Seek(int(l.fd), 0, os.SEEK_SET)
|
_, err := unix.Seek(int(l.fd), 0, os.SEEK_SET)
|
||||||
@ -128,6 +169,7 @@ func (l *lockfile) Modified() (bool, error) {
|
|||||||
return l.lw != lw, nil
|
return l.lw != lw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TouchedSince indicates if the lock file has been touched since the specified time
|
||||||
func (l *lockfile) TouchedSince(when time.Time) bool {
|
func (l *lockfile) TouchedSince(when time.Time) bool {
|
||||||
st := unix.Stat_t{}
|
st := unix.Stat_t{}
|
||||||
err := unix.Fstat(int(l.fd), &st)
|
err := unix.Fstat(int(l.fd), &st)
|
||||||
@ -137,3 +179,8 @@ func (l *lockfile) TouchedSince(when time.Time) bool {
|
|||||||
touched := time.Unix(statTMtimeUnix(st))
|
touched := time.Unix(statTMtimeUnix(st))
|
||||||
return when.Before(touched)
|
return when.Before(touched)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsRWLock indicates if the lock file is a read-write lock
|
||||||
|
func (l *lockfile) IsReadWrite() bool {
|
||||||
|
return (l.locktype == unix.F_WRLCK)
|
||||||
|
}
|
||||||
|
13
vendor/github.com/containers/storage/storageversion/version_lib.go
generated
vendored
13
vendor/github.com/containers/storage/storageversion/version_lib.go
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
// +build !containersstorageautogen
|
|
||||||
|
|
||||||
// Package storageversion is auto-generated at build-time
|
|
||||||
package storageversion
|
|
||||||
|
|
||||||
// Default build-time variable for library-import.
|
|
||||||
// This file is overridden on build with build-time informations.
|
|
||||||
const (
|
|
||||||
GitCommit string = "library-import"
|
|
||||||
Version string = "library-import"
|
|
||||||
BuildTime string = "library-import"
|
|
||||||
IAmStatic string = "library-import"
|
|
||||||
)
|
|
833
vendor/github.com/containers/storage/store.go
generated
vendored
833
vendor/github.com/containers/storage/store.go
generated
vendored
File diff suppressed because it is too large
Load Diff
19
vendor/github.com/containers/storage/vendor.conf
generated
vendored
Normal file
19
vendor/github.com/containers/storage/vendor.conf
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
github.com/BurntSushi/toml master
|
||||||
|
github.com/Microsoft/go-winio 307e919c663683a9000576fdc855acaf9534c165
|
||||||
|
github.com/Microsoft/hcsshim 0f615c198a84e0344b4ed49c464d8833d4648dfc
|
||||||
|
github.com/Sirupsen/logrus 61e43dc76f7ee59a82bdf3d71033dc12bea4c77d
|
||||||
|
github.com/docker/engine-api 4290f40c056686fcaa5c9caf02eac1dde9315adf
|
||||||
|
github.com/docker/go-connections eb315e36415380e7c2fdee175262560ff42359da
|
||||||
|
github.com/docker/go-units 0dadbb0345b35ec7ef35e228dabb8de89a65bf52
|
||||||
|
github.com/go-check/check 20d25e2804050c1cd24a7eea1e7a6447dd0e74ec
|
||||||
|
github.com/mattn/go-shellwords 753a2322a99f87c0eff284980e77f53041555bc6
|
||||||
|
github.com/mistifyio/go-zfs c0224de804d438efd11ea6e52ada8014537d6062
|
||||||
|
github.com/opencontainers/runc 6c22e77604689db8725fa866f0f2ec0b3e8c3a07
|
||||||
|
github.com/opencontainers/selinux ba1aefe8057f1d0cfb8e88d0ec1dc85925ef987d
|
||||||
|
github.com/pborman/uuid 1b00554d822231195d1babd97ff4a781231955c9
|
||||||
|
github.com/pkg/errors master
|
||||||
|
github.com/tchap/go-patricia v2.2.6
|
||||||
|
github.com/vbatts/tar-split bd4c5d64c3e9297f410025a3b1bd0c58f659e721
|
||||||
|
github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
|
||||||
|
golang.org/x/net f2499483f923065a842d38eb4c7f1927e6fc6e6d
|
||||||
|
golang.org/x/sys d75a52659825e75fff6158388dddc6a5b04f9ba5
|
Loading…
Reference in New Issue
Block a user