Merge pull request #1195 from rhatdan/VENDOR
Update vendor containers/storage
This commit is contained in:
commit
ba0f2825a0
|
|
@ -9,7 +9,7 @@ require (
|
|||
github.com/containernetworking/plugins v1.1.1
|
||||
github.com/containers/image/v5 v5.23.1-0.20221015133641-1921a1993c67
|
||||
github.com/containers/ocicrypt v1.1.6
|
||||
github.com/containers/storage v1.43.1-0.20221017123904-a4d4fe98e37d
|
||||
github.com/containers/storage v1.43.1-0.20221024131621-fae5bbf607fc
|
||||
github.com/coreos/go-systemd/v22 v22.4.0
|
||||
github.com/cyphar/filepath-securejoin v0.2.3
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
|
|
|
|||
1320
common/go.sum
1320
common/go.sum
File diff suppressed because it is too large
Load Diff
|
|
@ -68,11 +68,24 @@ type Container struct {
|
|||
|
||||
// rwContainerStore provides bookkeeping for information about Containers.
|
||||
type rwContainerStore interface {
|
||||
fileBasedStore
|
||||
metadataStore
|
||||
containerBigDataStore
|
||||
flaggableStore
|
||||
|
||||
// startWriting makes sure the store is fresh, and locks it for writing.
|
||||
// If this succeeds, the caller MUST call stopWriting().
|
||||
startWriting() error
|
||||
|
||||
// stopWriting releases locks obtained by startWriting.
|
||||
stopWriting()
|
||||
|
||||
// startReading makes sure the store is fresh, and locks it for reading.
|
||||
// If this succeeds, the caller MUST call stopReading().
|
||||
startReading() error
|
||||
|
||||
// stopReading releases locks obtained by startReading.
|
||||
stopReading()
|
||||
|
||||
// Create creates a container that has a specified ID (or generates a
|
||||
// random one if an empty value is supplied) and optional names,
|
||||
// based on the specified image, using the specified layer as its
|
||||
|
|
@ -163,6 +176,77 @@ func (c *Container) MountOpts() []string {
|
|||
}
|
||||
}
|
||||
|
||||
// startWritingWithReload makes sure the store is fresh if canReload, and locks it for writing.
|
||||
// If this succeeds, the caller MUST call stopWriting().
|
||||
//
|
||||
// This is an internal implementation detail of containerStore construction, every other caller
|
||||
// should use startWriting() instead.
|
||||
func (r *containerStore) startWritingWithReload(canReload bool) error {
|
||||
r.lockfile.Lock()
|
||||
succeeded := false
|
||||
defer func() {
|
||||
if !succeeded {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
if canReload {
|
||||
if err := r.ReloadIfChanged(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
succeeded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// startWriting makes sure the store is fresh, and locks it for writing.
|
||||
// If this succeeds, the caller MUST call stopWriting().
|
||||
func (r *containerStore) startWriting() error {
|
||||
return r.startWritingWithReload(true)
|
||||
}
|
||||
|
||||
// stopWriting releases locks obtained by startWriting.
|
||||
func (r *containerStore) stopWriting() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
// startReading makes sure the store is fresh, and locks it for reading.
|
||||
// If this succeeds, the caller MUST call stopReading().
|
||||
func (r *containerStore) startReading() error {
|
||||
r.lockfile.RLock()
|
||||
succeeded := false
|
||||
defer func() {
|
||||
if !succeeded {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
if err := r.ReloadIfChanged(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
succeeded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// stopReading releases locks obtained by startReading.
|
||||
func (r *containerStore) stopReading() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
// ReloadIfChanged reloads the contents of the store from disk if it is changed.
|
||||
func (r *containerStore) ReloadIfChanged() error {
|
||||
r.loadMut.Lock()
|
||||
defer r.loadMut.Unlock()
|
||||
|
||||
modified, err := r.lockfile.Modified()
|
||||
if err == nil && modified {
|
||||
return r.Load()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *containerStore) Containers() ([]Container, error) {
|
||||
containers := make([]Container, len(r.containers))
|
||||
for i := range r.containers {
|
||||
|
|
@ -183,6 +267,8 @@ func (r *containerStore) datapath(id, key string) string {
|
|||
return filepath.Join(r.datadir(id), makeBigDataBaseName(key))
|
||||
}
|
||||
|
||||
// Load reloads the contents of the store from disk. It should be called
|
||||
// with the lock held.
|
||||
func (r *containerStore) Load() error {
|
||||
needSave := false
|
||||
rpath := r.containerspath()
|
||||
|
|
@ -221,8 +307,10 @@ func (r *containerStore) Load() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Save saves the contents of the store to disk. It should be called with
|
||||
// the lock held.
|
||||
func (r *containerStore) Save() error {
|
||||
if !r.Locked() {
|
||||
if !r.lockfile.Locked() {
|
||||
return errors.New("container store is not locked")
|
||||
}
|
||||
rpath := r.containerspath()
|
||||
|
|
@ -236,7 +324,7 @@ func (r *containerStore) Save() error {
|
|||
if err := ioutils.AtomicWriteFile(rpath, jdata, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.Touch()
|
||||
return r.lockfile.Touch()
|
||||
}
|
||||
|
||||
func newContainerStore(dir string) (rwContainerStore, error) {
|
||||
|
|
@ -255,8 +343,10 @@ func newContainerStore(dir string) (rwContainerStore, error) {
|
|||
bylayer: make(map[string]*Container),
|
||||
byname: make(map[string]*Container),
|
||||
}
|
||||
cstore.Lock()
|
||||
defer cstore.Unlock()
|
||||
if err := cstore.startWritingWithReload(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cstore.stopWriting()
|
||||
if err := cstore.Load(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -595,46 +685,3 @@ func (r *containerStore) Wipe() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *containerStore) Lock() {
|
||||
r.lockfile.Lock()
|
||||
}
|
||||
|
||||
func (r *containerStore) RLock() {
|
||||
r.lockfile.RLock()
|
||||
}
|
||||
|
||||
func (r *containerStore) Unlock() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
func (r *containerStore) Touch() error {
|
||||
return r.lockfile.Touch()
|
||||
}
|
||||
|
||||
func (r *containerStore) Modified() (bool, error) {
|
||||
return r.lockfile.Modified()
|
||||
}
|
||||
|
||||
func (r *containerStore) IsReadWrite() bool {
|
||||
return r.lockfile.IsReadWrite()
|
||||
}
|
||||
|
||||
func (r *containerStore) TouchedSince(when time.Time) bool {
|
||||
return r.lockfile.TouchedSince(when)
|
||||
}
|
||||
|
||||
func (r *containerStore) Locked() bool {
|
||||
return r.lockfile.Locked()
|
||||
}
|
||||
|
||||
func (r *containerStore) ReloadIfChanged() error {
|
||||
r.loadMut.Lock()
|
||||
defer r.loadMut.Unlock()
|
||||
|
||||
modified, err := r.Modified()
|
||||
if err == nil && modified {
|
||||
return r.Load()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ const (
|
|||
// is true (512 is a buffer for label metadata, 128 is the
|
||||
// number of lowers we want to be able to use without having
|
||||
// to use bind mounts to get all the way to the kernel limit).
|
||||
// ((idLength + len(linkDir) + 1) * maxDepth) <= (pageSize - 512)
|
||||
// ((idLength + len(linkDir) + 1) * 128) <= (pageSize - 512)
|
||||
idLength = 26
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -96,10 +96,16 @@ type Image struct {
|
|||
|
||||
// roImageStore provides bookkeeping for information about Images.
|
||||
type roImageStore interface {
|
||||
roFileBasedStore
|
||||
roMetadataStore
|
||||
roBigDataStore
|
||||
|
||||
// startReading makes sure the store is fresh, and locks it for reading.
|
||||
// If this succeeds, the caller MUST call stopReading().
|
||||
startReading() error
|
||||
|
||||
// stopReading releases locks obtained by startReading.
|
||||
stopReading()
|
||||
|
||||
// Exists checks if there is an image with the given ID or name.
|
||||
Exists(id string) bool
|
||||
|
||||
|
|
@ -119,11 +125,17 @@ type roImageStore interface {
|
|||
// rwImageStore provides bookkeeping for information about Images.
|
||||
type rwImageStore interface {
|
||||
roImageStore
|
||||
rwFileBasedStore
|
||||
rwMetadataStore
|
||||
rwImageBigDataStore
|
||||
flaggableStore
|
||||
|
||||
// startWriting makes sure the store is fresh, and locks it for writing.
|
||||
// If this succeeds, the caller MUST call stopWriting().
|
||||
startWriting() error
|
||||
|
||||
// stopWriting releases locks obtained by startWriting.
|
||||
stopWriting()
|
||||
|
||||
// Create creates an image that has a specified ID (or a random one) and
|
||||
// optional names, using the specified layer as its topmost (hopefully
|
||||
// read-only) layer. That layer can be referenced by multiple images.
|
||||
|
|
@ -182,6 +194,88 @@ func copyImageSlice(slice []*Image) []*Image {
|
|||
return nil
|
||||
}
|
||||
|
||||
// startWritingWithReload makes sure the store is fresh if canReload, and locks it for writing.
|
||||
// If this succeeds, the caller MUST call stopWriting().
|
||||
//
|
||||
// This is an internal implementation detail of imageStore construction, every other caller
|
||||
// should use startReading() instead.
|
||||
func (r *imageStore) startWritingWithReload(canReload bool) error {
|
||||
r.lockfile.Lock()
|
||||
succeeded := false
|
||||
defer func() {
|
||||
if !succeeded {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
if canReload {
|
||||
if err := r.ReloadIfChanged(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
succeeded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// startWriting makes sure the store is fresh, and locks it for writing.
|
||||
// If this succeeds, the caller MUST call stopWriting().
|
||||
func (r *imageStore) startWriting() error {
|
||||
return r.startWritingWithReload(true)
|
||||
}
|
||||
|
||||
// stopWriting releases locks obtained by startWriting.
|
||||
func (r *imageStore) stopWriting() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
// startReadingWithReload makes sure the store is fresh if canReload, and locks it for reading.
|
||||
// If this succeeds, the caller MUST call stopReading().
|
||||
//
|
||||
// This is an internal implementation detail of imageStore construction, every other caller
|
||||
// should use startReading() instead.
|
||||
func (r *imageStore) startReadingWithReload(canReload bool) error {
|
||||
r.lockfile.RLock()
|
||||
succeeded := false
|
||||
defer func() {
|
||||
if !succeeded {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
if canReload {
|
||||
if err := r.ReloadIfChanged(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
succeeded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// startReading makes sure the store is fresh, and locks it for reading.
|
||||
// If this succeeds, the caller MUST call stopReading().
|
||||
func (r *imageStore) startReading() error {
|
||||
return r.startReadingWithReload(true)
|
||||
}
|
||||
|
||||
// stopReading releases locks obtained by startReading.
|
||||
func (r *imageStore) stopReading() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
// ReloadIfChanged reloads the contents of the store from disk if it is changed.
|
||||
func (r *imageStore) ReloadIfChanged() error {
|
||||
r.loadMut.Lock()
|
||||
defer r.loadMut.Unlock()
|
||||
|
||||
modified, err := r.lockfile.Modified()
|
||||
if err == nil && modified {
|
||||
return r.Load()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *imageStore) Images() ([]Image, error) {
|
||||
images := make([]Image, len(r.images))
|
||||
for i := range r.images {
|
||||
|
|
@ -242,6 +336,8 @@ func (i *Image) recomputeDigests() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Load reloads the contents of the store from disk. It should be called
|
||||
// with the lock held.
|
||||
func (r *imageStore) Load() error {
|
||||
shouldSave := false
|
||||
rpath := r.imagespath()
|
||||
|
|
@ -277,10 +373,10 @@ func (r *imageStore) Load() error {
|
|||
list := digests[digest]
|
||||
digests[digest] = append(list, image)
|
||||
}
|
||||
image.ReadOnly = !r.IsReadWrite()
|
||||
image.ReadOnly = !r.lockfile.IsReadWrite()
|
||||
}
|
||||
}
|
||||
if shouldSave && (!r.IsReadWrite() || !r.Locked()) {
|
||||
if shouldSave && (!r.lockfile.IsReadWrite() || !r.lockfile.Locked()) {
|
||||
return ErrDuplicateImageNames
|
||||
}
|
||||
r.images = images
|
||||
|
|
@ -294,11 +390,13 @@ func (r *imageStore) Load() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Save saves the contents of the store to disk. It should be called with
|
||||
// the lock held.
|
||||
func (r *imageStore) Save() error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to modify the image store at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
if !r.Locked() {
|
||||
if !r.lockfile.Locked() {
|
||||
return errors.New("image store is not locked for writing")
|
||||
}
|
||||
rpath := r.imagespath()
|
||||
|
|
@ -312,7 +410,7 @@ func (r *imageStore) Save() error {
|
|||
if err := ioutils.AtomicWriteFile(rpath, jdata, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.Touch()
|
||||
return r.lockfile.Touch()
|
||||
}
|
||||
|
||||
func newImageStore(dir string) (rwImageStore, error) {
|
||||
|
|
@ -331,8 +429,10 @@ func newImageStore(dir string) (rwImageStore, error) {
|
|||
byname: make(map[string]*Image),
|
||||
bydigest: make(map[digest.Digest][]*Image),
|
||||
}
|
||||
istore.Lock()
|
||||
defer istore.Unlock()
|
||||
if err := istore.startWritingWithReload(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer istore.stopWriting()
|
||||
if err := istore.Load(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -352,8 +452,10 @@ func newROImageStore(dir string) (roImageStore, error) {
|
|||
byname: make(map[string]*Image),
|
||||
bydigest: make(map[digest.Digest][]*Image),
|
||||
}
|
||||
istore.RLock()
|
||||
defer istore.Unlock()
|
||||
if err := istore.startReadingWithReload(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer istore.stopReading()
|
||||
if err := istore.Load(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -373,7 +475,7 @@ func (r *imageStore) lookup(id string) (*Image, bool) {
|
|||
}
|
||||
|
||||
func (r *imageStore) ClearFlag(id string, flag string) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to clear flags on images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
image, ok := r.lookup(id)
|
||||
|
|
@ -385,7 +487,7 @@ func (r *imageStore) ClearFlag(id string, flag string) error {
|
|||
}
|
||||
|
||||
func (r *imageStore) SetFlag(id string, flag string, value interface{}) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to set flags on images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
image, ok := r.lookup(id)
|
||||
|
|
@ -400,7 +502,7 @@ func (r *imageStore) SetFlag(id string, flag string, value interface{}) error {
|
|||
}
|
||||
|
||||
func (r *imageStore) Create(id string, names []string, layer, metadata string, created time.Time, searchableDigest digest.Digest) (image *Image, err error) {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return nil, fmt.Errorf("not allowed to create new images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
if id == "" {
|
||||
|
|
@ -487,7 +589,7 @@ func (r *imageStore) Metadata(id string) (string, error) {
|
|||
}
|
||||
|
||||
func (r *imageStore) SetMetadata(id, metadata string) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to modify image metadata at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
if image, ok := r.lookup(id); ok {
|
||||
|
|
@ -506,7 +608,7 @@ func (i *Image) addNameToHistory(name string) {
|
|||
}
|
||||
|
||||
func (r *imageStore) updateNames(id string, names []string, op updateNameOperation) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to change image name assignments at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
image, ok := r.lookup(id)
|
||||
|
|
@ -533,7 +635,7 @@ func (r *imageStore) updateNames(id string, names []string, op updateNameOperati
|
|||
}
|
||||
|
||||
func (r *imageStore) Delete(id string) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to delete images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
image, ok := r.lookup(id)
|
||||
|
|
@ -669,7 +771,7 @@ func (r *imageStore) SetBigData(id, key string, data []byte, digestManifest func
|
|||
if key == "" {
|
||||
return fmt.Errorf("can't set empty name for image big data item: %w", ErrInvalidBigDataName)
|
||||
}
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to save data items associated with images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
image, ok := r.lookup(id)
|
||||
|
|
@ -750,7 +852,7 @@ func (r *imageStore) SetBigData(id, key string, data []byte, digestManifest func
|
|||
}
|
||||
|
||||
func (r *imageStore) Wipe() error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to delete images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
ids := make([]string, 0, len(r.byid))
|
||||
|
|
@ -764,46 +866,3 @@ func (r *imageStore) Wipe() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *imageStore) Lock() {
|
||||
r.lockfile.Lock()
|
||||
}
|
||||
|
||||
func (r *imageStore) RLock() {
|
||||
r.lockfile.RLock()
|
||||
}
|
||||
|
||||
func (r *imageStore) Unlock() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
func (r *imageStore) Touch() error {
|
||||
return r.lockfile.Touch()
|
||||
}
|
||||
|
||||
func (r *imageStore) Modified() (bool, error) {
|
||||
return r.lockfile.Modified()
|
||||
}
|
||||
|
||||
func (r *imageStore) IsReadWrite() bool {
|
||||
return r.lockfile.IsReadWrite()
|
||||
}
|
||||
|
||||
func (r *imageStore) TouchedSince(when time.Time) bool {
|
||||
return r.lockfile.TouchedSince(when)
|
||||
}
|
||||
|
||||
func (r *imageStore) Locked() bool {
|
||||
return r.lockfile.Locked()
|
||||
}
|
||||
|
||||
func (r *imageStore) ReloadIfChanged() error {
|
||||
r.loadMut.Lock()
|
||||
defer r.loadMut.Unlock()
|
||||
|
||||
modified, err := r.Modified()
|
||||
if err == nil && modified {
|
||||
return r.Load()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,10 +141,16 @@ type DiffOptions struct {
|
|||
// name, and keeping track of parent-child relationships, along with a list of
|
||||
// all known layers.
|
||||
type roLayerStore interface {
|
||||
roFileBasedStore
|
||||
roMetadataStore
|
||||
roLayerBigDataStore
|
||||
|
||||
// startReading makes sure the store is fresh, and locks it for reading.
|
||||
// If this succeeds, the caller MUST call stopReading().
|
||||
startReading() error
|
||||
|
||||
// stopReading releases locks obtained by startReading.
|
||||
stopReading()
|
||||
|
||||
// Exists checks if a layer with the specified name or ID is known.
|
||||
Exists(id string) bool
|
||||
|
||||
|
|
@ -194,11 +200,17 @@ type roLayerStore interface {
|
|||
// all known layers.
|
||||
type rwLayerStore interface {
|
||||
roLayerStore
|
||||
rwFileBasedStore
|
||||
rwMetadataStore
|
||||
flaggableStore
|
||||
rwLayerBigDataStore
|
||||
|
||||
// startWriting makes sure the store is fresh, and locks it for writing.
|
||||
// If this succeeds, the caller MUST call stopWriting().
|
||||
startWriting() error
|
||||
|
||||
// stopWriting releases locks obtained by startWriting.
|
||||
stopWriting()
|
||||
|
||||
// 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
|
||||
|
|
@ -304,6 +316,122 @@ func copyLayer(l *Layer) *Layer {
|
|||
}
|
||||
}
|
||||
|
||||
// startWritingWithReload makes sure the store is fresh if canReload, and locks it for writing.
|
||||
// If this succeeds, the caller MUST call stopWriting().
|
||||
//
|
||||
// This is an internal implementation detail of layerStore construction, every other caller
|
||||
// should use startWriting() instead.
|
||||
func (r *layerStore) startWritingWithReload(canReload bool) error {
|
||||
r.lockfile.Lock()
|
||||
succeeded := false
|
||||
defer func() {
|
||||
if !succeeded {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
if canReload {
|
||||
if err := r.ReloadIfChanged(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
succeeded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// startWriting makes sure the store is fresh, and locks it for writing.
|
||||
// If this succeeds, the caller MUST call stopWriting().
|
||||
func (r *layerStore) startWriting() error {
|
||||
return r.startWritingWithReload(true)
|
||||
}
|
||||
|
||||
// stopWriting releases locks obtained by startWriting.
|
||||
func (r *layerStore) stopWriting() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
// startReadingWithReload makes sure the store is fresh if canReload, and locks it for reading.
|
||||
// If this succeeds, the caller MUST call stopReading().
|
||||
//
|
||||
// This is an internal implementation detail of layerStore construction, every other caller
|
||||
// should use startReading() instead.
|
||||
func (r *layerStore) startReadingWithReload(canReload bool) error {
|
||||
r.lockfile.RLock()
|
||||
succeeded := false
|
||||
defer func() {
|
||||
if !succeeded {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
if canReload {
|
||||
if err := r.ReloadIfChanged(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
succeeded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// startReading makes sure the store is fresh, and locks it for reading.
|
||||
// If this succeeds, the caller MUST call stopReading().
|
||||
func (r *layerStore) startReading() error {
|
||||
return r.startReadingWithReload(true)
|
||||
}
|
||||
|
||||
// stopReading releases locks obtained by startReading.
|
||||
func (r *layerStore) stopReading() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
// Modified() checks if the most recent writer was a party other than the
|
||||
// last recorded writer. It should only be called with the lock held.
|
||||
func (r *layerStore) Modified() (bool, error) {
|
||||
var mmodified, tmodified bool
|
||||
lmodified, err := r.lockfile.Modified()
|
||||
if err != nil {
|
||||
return lmodified, err
|
||||
}
|
||||
if r.lockfile.IsReadWrite() {
|
||||
r.mountsLockfile.RLock()
|
||||
defer r.mountsLockfile.Unlock()
|
||||
mmodified, err = r.mountsLockfile.Modified()
|
||||
if err != nil {
|
||||
return lmodified, err
|
||||
}
|
||||
}
|
||||
|
||||
if lmodified || mmodified {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// If the layers.json file has been modified manually, then we have to
|
||||
// reload the storage in any case.
|
||||
info, err := os.Stat(r.layerspath())
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return false, fmt.Errorf("stat layers file: %w", err)
|
||||
}
|
||||
if info != nil {
|
||||
tmodified = info.ModTime() != r.layerspathModified
|
||||
}
|
||||
|
||||
return tmodified, nil
|
||||
}
|
||||
|
||||
// ReloadIfChanged reloads the contents of the store from disk if it is changed.
|
||||
func (r *layerStore) ReloadIfChanged() error {
|
||||
r.loadMut.Lock()
|
||||
defer r.loadMut.Unlock()
|
||||
|
||||
modified, err := r.Modified()
|
||||
if err == nil && modified {
|
||||
return r.Load()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *layerStore) Layers() ([]Layer, error) {
|
||||
layers := make([]Layer, len(r.layers))
|
||||
for i := range r.layers {
|
||||
|
|
@ -320,6 +448,8 @@ func (r *layerStore) layerspath() string {
|
|||
return filepath.Join(r.layerdir, "layers.json")
|
||||
}
|
||||
|
||||
// Load reloads the contents of the store from disk. It should be called
|
||||
// with the lock held.
|
||||
func (r *layerStore) Load() error {
|
||||
shouldSave := false
|
||||
rpath := r.layerspath()
|
||||
|
|
@ -341,7 +471,7 @@ func (r *layerStore) Load() error {
|
|||
names := make(map[string]*Layer)
|
||||
compressedsums := make(map[digest.Digest][]string)
|
||||
uncompressedsums := make(map[digest.Digest][]string)
|
||||
if r.IsReadWrite() {
|
||||
if r.lockfile.IsReadWrite() {
|
||||
selinux.ClearLabels()
|
||||
}
|
||||
if err = json.Unmarshal(data, &layers); len(data) == 0 || err == nil {
|
||||
|
|
@ -365,11 +495,11 @@ func (r *layerStore) Load() error {
|
|||
if layer.MountLabel != "" {
|
||||
selinux.ReserveLabel(layer.MountLabel)
|
||||
}
|
||||
layer.ReadOnly = !r.IsReadWrite()
|
||||
layer.ReadOnly = !r.lockfile.IsReadWrite()
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
if shouldSave && (!r.IsReadWrite() || !r.Locked()) {
|
||||
if shouldSave && (!r.lockfile.IsReadWrite() || !r.lockfile.Locked()) {
|
||||
return ErrDuplicateLayerNames
|
||||
}
|
||||
r.layers = layers
|
||||
|
|
@ -380,7 +510,7 @@ func (r *layerStore) Load() error {
|
|||
r.byuncompressedsum = uncompressedsums
|
||||
|
||||
// Load and merge information about which layers are mounted, and where.
|
||||
if r.IsReadWrite() {
|
||||
if r.lockfile.IsReadWrite() {
|
||||
r.mountsLockfile.RLock()
|
||||
defer r.mountsLockfile.Unlock()
|
||||
if err = r.loadMounts(); err != nil {
|
||||
|
|
@ -390,7 +520,7 @@ func (r *layerStore) Load() error {
|
|||
// Last step: as we’re writable, try to remove anything that a previous
|
||||
// user of this storage area marked for deletion but didn't manage to
|
||||
// actually delete.
|
||||
if r.Locked() {
|
||||
if r.lockfile.Locked() {
|
||||
for _, layer := range r.layers {
|
||||
if layer.Flags == nil {
|
||||
layer.Flags = make(map[string]interface{})
|
||||
|
|
@ -450,6 +580,8 @@ func (r *layerStore) loadMounts() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Save saves the contents of the store to disk. It should be called with
|
||||
// the lock held.
|
||||
func (r *layerStore) Save() error {
|
||||
r.mountsLockfile.Lock()
|
||||
defer r.mountsLockfile.Unlock()
|
||||
|
|
@ -460,10 +592,10 @@ func (r *layerStore) Save() error {
|
|||
}
|
||||
|
||||
func (r *layerStore) saveLayers() error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to modify the layer store at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
if !r.Locked() {
|
||||
if !r.lockfile.Locked() {
|
||||
return errors.New("layer store is not locked for writing")
|
||||
}
|
||||
rpath := r.layerspath()
|
||||
|
|
@ -477,11 +609,11 @@ func (r *layerStore) saveLayers() error {
|
|||
if err := ioutils.AtomicWriteFile(rpath, jldata, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.Touch()
|
||||
return r.lockfile.Touch()
|
||||
}
|
||||
|
||||
func (r *layerStore) saveMounts() error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to modify the layer store at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
if !r.mountsLockfile.Locked() {
|
||||
|
|
@ -539,8 +671,10 @@ func (s *store) newLayerStore(rundir string, layerdir string, driver drivers.Dri
|
|||
bymount: make(map[string]*Layer),
|
||||
byname: make(map[string]*Layer),
|
||||
}
|
||||
rlstore.Lock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.startWritingWithReload(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rlstore.stopWriting()
|
||||
if err := rlstore.Load(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -562,8 +696,10 @@ func newROLayerStore(rundir string, layerdir string, driver drivers.Driver) (roL
|
|||
bymount: make(map[string]*Layer),
|
||||
byname: make(map[string]*Layer),
|
||||
}
|
||||
rlstore.RLock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.startReadingWithReload(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rlstore.stopReading()
|
||||
if err := rlstore.Load(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -597,7 +733,7 @@ func (r *layerStore) Size(name string) (int64, error) {
|
|||
}
|
||||
|
||||
func (r *layerStore) ClearFlag(id string, flag string) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to clear flags on layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
layer, ok := r.lookup(id)
|
||||
|
|
@ -609,7 +745,7 @@ func (r *layerStore) ClearFlag(id string, flag string) error {
|
|||
}
|
||||
|
||||
func (r *layerStore) SetFlag(id string, flag string, value interface{}) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to set flags on layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
layer, ok := r.lookup(id)
|
||||
|
|
@ -684,7 +820,7 @@ func (r *layerStore) PutAdditionalLayer(id string, parentLayer *Layer, names []s
|
|||
}
|
||||
|
||||
func (r *layerStore) Put(id string, parentLayer *Layer, names []string, mountLabel string, options map[string]string, moreOptions *LayerOptions, writeable bool, flags map[string]interface{}, diff io.Reader) (*Layer, int64, error) {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return nil, -1, fmt.Errorf("not allowed to create new layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
if err := os.MkdirAll(r.rundir, 0700); err != nil {
|
||||
|
|
@ -889,7 +1025,7 @@ func (r *layerStore) Create(id string, parent *Layer, names []string, mountLabel
|
|||
}
|
||||
|
||||
func (r *layerStore) Mounted(id string) (int, error) {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return 0, fmt.Errorf("no mount information for layers at %q: %w", r.mountspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
r.mountsLockfile.RLock()
|
||||
|
|
@ -919,7 +1055,7 @@ func (r *layerStore) Mount(id string, options drivers.MountOpts) (string, error)
|
|||
|
||||
// You are not allowed to mount layers from readonly stores if they
|
||||
// are not mounted read/only.
|
||||
if !r.IsReadWrite() && !hasReadOnlyOpt(options.Options) {
|
||||
if !r.lockfile.IsReadWrite() && !hasReadOnlyOpt(options.Options) {
|
||||
return "", fmt.Errorf("not allowed to update mount locations for layers at %q: %w", r.mountspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
r.mountsLockfile.Lock()
|
||||
|
|
@ -969,7 +1105,7 @@ func (r *layerStore) Mount(id string, options drivers.MountOpts) (string, error)
|
|||
}
|
||||
|
||||
func (r *layerStore) Unmount(id string, force bool) (bool, error) {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return false, fmt.Errorf("not allowed to update mount locations for layers at %q: %w", r.mountspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
r.mountsLockfile.Lock()
|
||||
|
|
@ -1007,7 +1143,7 @@ func (r *layerStore) Unmount(id string, force bool) (bool, error) {
|
|||
}
|
||||
|
||||
func (r *layerStore) ParentOwners(id string) (uids, gids []int, err error) {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return nil, nil, fmt.Errorf("no mount information for layers at %q: %w", r.mountspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
r.mountsLockfile.RLock()
|
||||
|
|
@ -1082,7 +1218,7 @@ func (r *layerStore) removeName(layer *Layer, name string) {
|
|||
}
|
||||
|
||||
func (r *layerStore) updateNames(id string, names []string, op updateNameOperation) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to change layer name assignments at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
layer, ok := r.lookup(id)
|
||||
|
|
@ -1130,7 +1266,7 @@ func (r *layerStore) SetBigData(id, key string, data io.Reader) error {
|
|||
if key == "" {
|
||||
return fmt.Errorf("can't set empty name for layer big data item: %w", ErrInvalidBigDataName)
|
||||
}
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to save data items associated with layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
layer, ok := r.lookup(id)
|
||||
|
|
@ -1189,7 +1325,7 @@ func (r *layerStore) Metadata(id string) (string, error) {
|
|||
}
|
||||
|
||||
func (r *layerStore) SetMetadata(id, metadata string) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to modify layer metadata at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
if layer, ok := r.lookup(id); ok {
|
||||
|
|
@ -1215,7 +1351,7 @@ func layerHasIncompleteFlag(layer *Layer) bool {
|
|||
}
|
||||
|
||||
func (r *layerStore) deleteInternal(id string) error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to delete layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
layer, ok := r.lookup(id)
|
||||
|
|
@ -1346,7 +1482,7 @@ func (r *layerStore) Get(id string) (*Layer, error) {
|
|||
}
|
||||
|
||||
func (r *layerStore) Wipe() error {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to delete layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
ids := make([]string, 0, len(r.byid))
|
||||
|
|
@ -1611,7 +1747,7 @@ func (r *layerStore) ApplyDiff(to string, diff io.Reader) (size int64, err error
|
|||
}
|
||||
|
||||
func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions, diff io.Reader) (size int64, err error) {
|
||||
if !r.IsReadWrite() {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return -1, fmt.Errorf("not allowed to modify layer contents at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
|
||||
}
|
||||
|
||||
|
|
@ -1867,77 +2003,6 @@ func (r *layerStore) LayersByUncompressedDigest(d digest.Digest) ([]Layer, error
|
|||
return r.layersByDigestMap(r.byuncompressedsum, d)
|
||||
}
|
||||
|
||||
func (r *layerStore) Lock() {
|
||||
r.lockfile.Lock()
|
||||
}
|
||||
|
||||
func (r *layerStore) RLock() {
|
||||
r.lockfile.RLock()
|
||||
}
|
||||
|
||||
func (r *layerStore) Unlock() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
func (r *layerStore) Touch() error {
|
||||
return r.lockfile.Touch()
|
||||
}
|
||||
|
||||
func (r *layerStore) Modified() (bool, error) {
|
||||
var mmodified, tmodified bool
|
||||
lmodified, err := r.lockfile.Modified()
|
||||
if err != nil {
|
||||
return lmodified, err
|
||||
}
|
||||
if r.IsReadWrite() {
|
||||
r.mountsLockfile.RLock()
|
||||
defer r.mountsLockfile.Unlock()
|
||||
mmodified, err = r.mountsLockfile.Modified()
|
||||
if err != nil {
|
||||
return lmodified, err
|
||||
}
|
||||
}
|
||||
|
||||
if lmodified || mmodified {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// If the layers.json file has been modified manually, then we have to
|
||||
// reload the storage in any case.
|
||||
info, err := os.Stat(r.layerspath())
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return false, fmt.Errorf("stat layers file: %w", err)
|
||||
}
|
||||
if info != nil {
|
||||
tmodified = info.ModTime() != r.layerspathModified
|
||||
}
|
||||
|
||||
return tmodified, nil
|
||||
}
|
||||
|
||||
func (r *layerStore) IsReadWrite() bool {
|
||||
return r.lockfile.IsReadWrite()
|
||||
}
|
||||
|
||||
func (r *layerStore) TouchedSince(when time.Time) bool {
|
||||
return r.lockfile.TouchedSince(when)
|
||||
}
|
||||
|
||||
func (r *layerStore) Locked() bool {
|
||||
return r.lockfile.Locked()
|
||||
}
|
||||
|
||||
func (r *layerStore) ReloadIfChanged() error {
|
||||
r.loadMut.Lock()
|
||||
defer r.loadMut.Unlock()
|
||||
|
||||
modified, err := r.Modified()
|
||||
if err == nil && modified {
|
||||
return r.Load()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func closeAll(closes ...func() error) (rErr error) {
|
||||
for _, f := range closes {
|
||||
if err := f(); err != nil {
|
||||
|
|
|
|||
|
|
@ -527,6 +527,9 @@ func (ta *tarAppender) addTarFile(path, name string) error {
|
|||
if err := ReadUserXattrToTarHeader(path, hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ReadFileFlagsToTarHeader(path, hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
if ta.CopyPass {
|
||||
copyPassHeader(hdr)
|
||||
}
|
||||
|
|
@ -770,6 +773,15 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
|
|||
|
||||
}
|
||||
|
||||
// We defer setting flags on directories until the end of
|
||||
// Unpack or UnpackLayer in case setting them makes the
|
||||
// directory immutable.
|
||||
if hdr.Typeflag != tar.TypeDir {
|
||||
if err := WriteFileFlagsFromTarHeader(path, hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"errors": errs,
|
||||
|
|
@ -1101,6 +1113,9 @@ loop:
|
|||
if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := WriteFileFlagsFromTarHeader(path, hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package archive
|
||||
|
|
@ -29,6 +30,7 @@ func statDifferent(oldStat *system.StatT, oldInfo *FileInfo, newStat *system.Sta
|
|||
if oldStat.Mode() != newStat.Mode() ||
|
||||
ownerChanged ||
|
||||
oldStat.Rdev() != newStat.Rdev() ||
|
||||
oldStat.Flags() != newStat.Flags() ||
|
||||
// Don't look at size for dirs, its not a good measure of change
|
||||
(oldStat.Mode()&unix.S_IFDIR != unix.S_IFDIR &&
|
||||
(!sameFsTimeSpec(oldStat.Mtim(), newStat.Mtim()) || (oldStat.Size() != newStat.Size()))) {
|
||||
|
|
|
|||
|
|
@ -145,6 +145,9 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
|
|||
return nil
|
||||
}
|
||||
if _, exists := unpackedPaths[path]; !exists {
|
||||
if err := resetImmutable(path, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
err := os.RemoveAll(path)
|
||||
return err
|
||||
}
|
||||
|
|
@ -156,6 +159,9 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
|
|||
} else {
|
||||
originalBase := base[len(WhiteoutPrefix):]
|
||||
originalPath := filepath.Join(dir, originalBase)
|
||||
if err := resetImmutable(originalPath, nil); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := os.RemoveAll(originalPath); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -165,7 +171,15 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
|
|||
// The only exception is when it is a directory *and* the file from
|
||||
// the layer is also a directory. Then we want to merge them (i.e.
|
||||
// just apply the metadata from the layer).
|
||||
//
|
||||
// We always reset the immutable flag (if present) to allow metadata
|
||||
// changes and to allow directory modification. The flag will be
|
||||
// re-applied based on the contents of hdr either at the end for
|
||||
// directories or in createTarFile otherwise.
|
||||
if fi, err := os.Lstat(path); err == nil {
|
||||
if err := resetImmutable(path, &fi); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) {
|
||||
if err := os.RemoveAll(path); err != nil {
|
||||
return 0, err
|
||||
|
|
@ -215,6 +229,9 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
|
|||
if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := WriteFileFlagsFromTarHeader(path, hdr); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return size, nil
|
||||
|
|
|
|||
167
common/vendor/github.com/containers/storage/pkg/archive/fflags_bsd.go
generated
vendored
Normal file
167
common/vendor/github.com/containers/storage/pkg/archive/fflags_bsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/storage/pkg/system"
|
||||
)
|
||||
|
||||
const (
|
||||
paxSCHILYFflags = "SCHILY.fflags"
|
||||
)
|
||||
|
||||
var (
|
||||
flagNameToValue = map[string]uint32{
|
||||
"sappnd": system.SF_APPEND,
|
||||
"sappend": system.SF_APPEND,
|
||||
"arch": system.SF_ARCHIVED,
|
||||
"archived": system.SF_ARCHIVED,
|
||||
"schg": system.SF_IMMUTABLE,
|
||||
"schange": system.SF_IMMUTABLE,
|
||||
"simmutable": system.SF_IMMUTABLE,
|
||||
"sunlnk": system.SF_NOUNLINK,
|
||||
"sunlink": system.SF_NOUNLINK,
|
||||
"snapshot": system.SF_SNAPSHOT,
|
||||
"uappnd": system.UF_APPEND,
|
||||
"uappend": system.UF_APPEND,
|
||||
"uarch": system.UF_ARCHIVE,
|
||||
"uarchive": system.UF_ARCHIVE,
|
||||
"hidden": system.UF_HIDDEN,
|
||||
"uhidden": system.UF_HIDDEN,
|
||||
"uchg": system.UF_IMMUTABLE,
|
||||
"uchange": system.UF_IMMUTABLE,
|
||||
"uimmutable": system.UF_IMMUTABLE,
|
||||
"uunlnk": system.UF_NOUNLINK,
|
||||
"uunlink": system.UF_NOUNLINK,
|
||||
"offline": system.UF_OFFLINE,
|
||||
"uoffline": system.UF_OFFLINE,
|
||||
"opaque": system.UF_OPAQUE,
|
||||
"rdonly": system.UF_READONLY,
|
||||
"urdonly": system.UF_READONLY,
|
||||
"readonly": system.UF_READONLY,
|
||||
"ureadonly": system.UF_READONLY,
|
||||
"reparse": system.UF_REPARSE,
|
||||
"ureparse": system.UF_REPARSE,
|
||||
"sparse": system.UF_SPARSE,
|
||||
"usparse": system.UF_SPARSE,
|
||||
"system": system.UF_SYSTEM,
|
||||
"usystem": system.UF_SYSTEM,
|
||||
}
|
||||
// Only include the short names for the reverse map
|
||||
flagValueToName = map[uint32]string{
|
||||
system.SF_APPEND: "sappnd",
|
||||
system.SF_ARCHIVED: "arch",
|
||||
system.SF_IMMUTABLE: "schg",
|
||||
system.SF_NOUNLINK: "sunlnk",
|
||||
system.SF_SNAPSHOT: "snapshot",
|
||||
system.UF_APPEND: "uappnd",
|
||||
system.UF_ARCHIVE: "uarch",
|
||||
system.UF_HIDDEN: "hidden",
|
||||
system.UF_IMMUTABLE: "uchg",
|
||||
system.UF_NOUNLINK: "uunlnk",
|
||||
system.UF_OFFLINE: "offline",
|
||||
system.UF_OPAQUE: "opaque",
|
||||
system.UF_READONLY: "rdonly",
|
||||
system.UF_REPARSE: "reparse",
|
||||
system.UF_SPARSE: "sparse",
|
||||
system.UF_SYSTEM: "system",
|
||||
}
|
||||
)
|
||||
|
||||
func parseFileFlags(fflags string) (uint32, uint32, error) {
|
||||
var set, clear uint32 = 0, 0
|
||||
for _, fflag := range strings.Split(fflags, ",") {
|
||||
isClear := false
|
||||
if strings.HasPrefix(fflag, "no") {
|
||||
isClear = true
|
||||
fflag = strings.TrimPrefix(fflag, "no")
|
||||
}
|
||||
if value, ok := flagNameToValue[fflag]; ok {
|
||||
if isClear {
|
||||
clear |= value
|
||||
} else {
|
||||
set |= value
|
||||
}
|
||||
} else {
|
||||
return 0, 0, fmt.Errorf("parsing file flags, unrecognised token: %s", fflag)
|
||||
}
|
||||
}
|
||||
return set, clear, nil
|
||||
}
|
||||
|
||||
func formatFileFlags(fflags uint32) (string, error) {
|
||||
var res = []string{}
|
||||
for fflags != 0 {
|
||||
// Extract lowest set bit
|
||||
fflag := uint32(1) << bits.TrailingZeros32(fflags)
|
||||
if name, ok := flagValueToName[fflag]; ok {
|
||||
res = append(res, name)
|
||||
} else {
|
||||
return "", fmt.Errorf("formatting file flags, unrecognised flag: %x", fflag)
|
||||
}
|
||||
fflags &= ^fflag
|
||||
}
|
||||
return strings.Join(res, ","), nil
|
||||
}
|
||||
|
||||
func ReadFileFlagsToTarHeader(path string, hdr *tar.Header) error {
|
||||
st, err := system.Lstat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fflags, err := formatFileFlags(st.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if fflags != "" {
|
||||
if hdr.PAXRecords == nil {
|
||||
hdr.PAXRecords = map[string]string{}
|
||||
}
|
||||
hdr.PAXRecords[paxSCHILYFflags] = fflags
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteFileFlagsFromTarHeader(path string, hdr *tar.Header) error {
|
||||
if fflags, ok := hdr.PAXRecords[paxSCHILYFflags]; ok {
|
||||
var set, clear uint32
|
||||
set, clear, err := parseFileFlags(fflags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Apply the delta to the existing file flags
|
||||
st, err := system.Lstat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return system.Lchflags(path, (st.Flags() & ^clear)|set)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func resetImmutable(path string, fi *os.FileInfo) error {
|
||||
var flags uint32
|
||||
if fi != nil {
|
||||
flags = (*fi).Sys().(*syscall.Stat_t).Flags
|
||||
} else {
|
||||
st, err := system.Lstat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
flags = st.Flags()
|
||||
}
|
||||
if flags&(system.SF_IMMUTABLE|system.UF_IMMUTABLE) != 0 {
|
||||
flags &= ^(system.SF_IMMUTABLE | system.UF_IMMUTABLE)
|
||||
return system.Lchflags(path, flags)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
21
common/vendor/github.com/containers/storage/pkg/archive/fflags_unsupported.go
generated
vendored
Normal file
21
common/vendor/github.com/containers/storage/pkg/archive/fflags_unsupported.go
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//go:build !freebsd
|
||||
// +build !freebsd
|
||||
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"os"
|
||||
)
|
||||
|
||||
func ReadFileFlagsToTarHeader(path string, hdr *tar.Header) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteFileFlagsFromTarHeader(path string, hdr *tar.Header) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func resetImmutable(path string, fi *os.FileInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -246,7 +246,7 @@ func (l *lockfile) Modified() (bool, error) {
|
|||
panic("attempted to check last-writer in lockfile without locking it first")
|
||||
}
|
||||
defer l.stateMutex.Unlock()
|
||||
currentLW := make([]byte, len(l.lw))
|
||||
currentLW := make([]byte, lastWriterIDSize)
|
||||
n, err := unix.Pread(int(l.fd), currentLW, 0)
|
||||
if err != nil {
|
||||
return true, err
|
||||
|
|
|
|||
|
|
@ -22,9 +22,8 @@ func unmount(target string, flags int) error {
|
|||
// can be returned if flags are invalid, so this code
|
||||
// assumes that the flags value is always correct.
|
||||
return nil
|
||||
default:
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return &mountError{
|
||||
|
|
|
|||
56
common/vendor/github.com/containers/storage/pkg/system/lchflags_bsd.go
generated
vendored
Normal file
56
common/vendor/github.com/containers/storage/pkg/system/lchflags_bsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Flag values from <sys/stat.h>
|
||||
const (
|
||||
/*
|
||||
* Definitions of flags stored in file flags word.
|
||||
*
|
||||
* Super-user and owner changeable flags.
|
||||
*/
|
||||
UF_SETTABLE uint32 = 0x0000ffff /* mask of owner changeable flags */
|
||||
UF_NODUMP uint32 = 0x00000001 /* do not dump file */
|
||||
UF_IMMUTABLE uint32 = 0x00000002 /* file may not be changed */
|
||||
UF_APPEND uint32 = 0x00000004 /* writes to file may only append */
|
||||
UF_OPAQUE uint32 = 0x00000008 /* directory is opaque wrt. union */
|
||||
UF_NOUNLINK uint32 = 0x00000010 /* file may not be removed or renamed */
|
||||
|
||||
UF_SYSTEM uint32 = 0x00000080 /* Windows system file bit */
|
||||
UF_SPARSE uint32 = 0x00000100 /* sparse file */
|
||||
UF_OFFLINE uint32 = 0x00000200 /* file is offline */
|
||||
UF_REPARSE uint32 = 0x00000400 /* Windows reparse point file bit */
|
||||
UF_ARCHIVE uint32 = 0x00000800 /* file needs to be archived */
|
||||
UF_READONLY uint32 = 0x00001000 /* Windows readonly file bit */
|
||||
/* This is the same as the MacOS X definition of UF_HIDDEN. */
|
||||
UF_HIDDEN uint32 = 0x00008000 /* file is hidden */
|
||||
|
||||
/*
|
||||
* Super-user changeable flags.
|
||||
*/
|
||||
SF_SETTABLE uint32 = 0xffff0000 /* mask of superuser changeable flags */
|
||||
SF_ARCHIVED uint32 = 0x00010000 /* file is archived */
|
||||
SF_IMMUTABLE uint32 = 0x00020000 /* file may not be changed */
|
||||
SF_APPEND uint32 = 0x00040000 /* writes to file may only append */
|
||||
SF_NOUNLINK uint32 = 0x00100000 /* file may not be removed or renamed */
|
||||
SF_SNAPSHOT uint32 = 0x00200000 /* snapshot inode */
|
||||
)
|
||||
|
||||
func Lchflags(path string, flags uint32) error {
|
||||
p, err := unix.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _, e1 := unix.Syscall(unix.SYS_LCHFLAGS, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
|
||||
if e1 != 0 {
|
||||
return e1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containers/storage/pkg/mount"
|
||||
|
|
@ -34,14 +36,24 @@ func EnsureRemoveAll(dir string) error {
|
|||
}
|
||||
|
||||
for {
|
||||
if err := resetFileFlags(dir); err != nil {
|
||||
return fmt.Errorf("resetting file flags: %w", err)
|
||||
}
|
||||
err := os.RemoveAll(dir)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the RemoveAll fails with a permission error, we
|
||||
// may have immutable files so try to remove the
|
||||
// immutable flag and redo the RemoveAll.
|
||||
if errors.Is(err, syscall.EPERM) {
|
||||
if err = resetFileFlags(dir); err != nil {
|
||||
return fmt.Errorf("resetting file flags: %w", err)
|
||||
}
|
||||
err = os.RemoveAll(dir)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
pe, ok := err.(*os.PathError)
|
||||
if !ok {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -3,28 +3,13 @@ package system
|
|||
import (
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func lchflags(path string, flags int) (err error) {
|
||||
p, err := unix.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _, e1 := unix.Syscall(unix.SYS_LCHFLAGS, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
|
||||
if e1 != 0 {
|
||||
return e1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset file flags in a directory tree. This allows EnsureRemoveAll
|
||||
// to delete trees which have the immutable flag set.
|
||||
func resetFileFlags(dir string) error {
|
||||
return filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err := lchflags(path, 0); err != nil {
|
||||
if err := Lchflags(path, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
12
common/vendor/github.com/containers/storage/pkg/system/stat_common.go
generated
vendored
Normal file
12
common/vendor/github.com/containers/storage/pkg/system/stat_common.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//go:build !freebsd
|
||||
// +build !freebsd
|
||||
|
||||
package system
|
||||
|
||||
type platformStatT struct {
|
||||
}
|
||||
|
||||
// Flags return file flags if supported or zero otherwise
|
||||
func (s StatT) Flags() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -2,12 +2,23 @@ package system
|
|||
|
||||
import "syscall"
|
||||
|
||||
type platformStatT struct {
|
||||
flags uint32
|
||||
}
|
||||
|
||||
// Flags return file flags if supported or zero otherwise
|
||||
func (s StatT) Flags() uint32 {
|
||||
return s.flags
|
||||
}
|
||||
|
||||
// fromStatT converts a syscall.Stat_t type to a system.Stat_t type
|
||||
func fromStatT(s *syscall.Stat_t) (*StatT, error) {
|
||||
return &StatT{size: s.Size,
|
||||
st := &StatT{size: s.Size,
|
||||
mode: uint32(s.Mode),
|
||||
uid: s.Uid,
|
||||
gid: s.Gid,
|
||||
rdev: uint64(s.Rdev),
|
||||
mtim: s.Mtimespec}, nil
|
||||
mtim: s.Mtimespec}
|
||||
st.flags = s.Flags
|
||||
return st, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package system
|
||||
|
|
@ -17,6 +18,7 @@ type StatT struct {
|
|||
rdev uint64
|
||||
size int64
|
||||
mtim syscall.Timespec
|
||||
platformStatT
|
||||
}
|
||||
|
||||
// Mode returns file's permission mode.
|
||||
|
|
|
|||
|
|
@ -50,36 +50,6 @@ var (
|
|||
storesLock sync.Mutex
|
||||
)
|
||||
|
||||
// roFileBasedStore wraps up the methods of the various types of file-based
|
||||
// data stores that we implement which are needed for both read-only and
|
||||
// read-write files.
|
||||
type roFileBasedStore interface {
|
||||
Locker
|
||||
|
||||
// Load reloads the contents of the store from disk. It should be called
|
||||
// with the lock held.
|
||||
Load() error
|
||||
|
||||
// ReloadIfChanged reloads the contents of the store from disk if it is changed.
|
||||
ReloadIfChanged() error
|
||||
}
|
||||
|
||||
// rwFileBasedStore wraps up the methods of various types of file-based data
|
||||
// stores that we implement using read-write files.
|
||||
type rwFileBasedStore interface {
|
||||
// Save saves the contents of the store to disk. It should be called with
|
||||
// the lock held, and Touch() should be called afterward before releasing the
|
||||
// lock.
|
||||
Save() error
|
||||
}
|
||||
|
||||
// fileBasedStore wraps up the common methods of various types of file-based
|
||||
// data stores that we implement.
|
||||
type fileBasedStore interface {
|
||||
roFileBasedStore
|
||||
rwFileBasedStore
|
||||
}
|
||||
|
||||
// roMetadataStore wraps a method for reading metadata associated with an ID.
|
||||
type roMetadataStore interface {
|
||||
// Metadata reads metadata associated with an item with the specified ID.
|
||||
|
|
@ -694,10 +664,8 @@ func GetStore(options types.StoreOptions) (Store, error) {
|
|||
if err := os.MkdirAll(options.GraphRoot, 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, subdir := range []string{"mounts", "tmp", options.GraphDriverName} {
|
||||
if err := os.MkdirAll(filepath.Join(options.GraphRoot, subdir), 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Join(options.GraphRoot, options.GraphDriverName), 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
graphLock, err := GetLockfile(filepath.Join(options.GraphRoot, "storage.lock"))
|
||||
|
|
@ -991,11 +959,10 @@ func (s *store) readAllLayerStores(fn func(store roLayerStore) (bool, error)) (b
|
|||
}
|
||||
for _, s := range layerStores {
|
||||
store := s
|
||||
store.RLock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startReading(); err != nil {
|
||||
return true, err
|
||||
}
|
||||
defer store.stopReading()
|
||||
if done, err := fn(store); done {
|
||||
return true, err
|
||||
}
|
||||
|
|
@ -1012,11 +979,10 @@ func (s *store) writeToLayerStore(fn func(store rwLayerStore) error) error {
|
|||
return err
|
||||
}
|
||||
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startWriting(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer store.stopWriting()
|
||||
return fn(store)
|
||||
}
|
||||
|
||||
|
|
@ -1079,11 +1045,10 @@ func (s *store) readAllImageStores(fn func(store roImageStore) (bool, error)) (b
|
|||
}
|
||||
for _, s := range ImageStores {
|
||||
store := s
|
||||
store.RLock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startReading(); err != nil {
|
||||
return true, err
|
||||
}
|
||||
defer store.stopReading()
|
||||
if done, err := fn(store); done {
|
||||
return true, err
|
||||
}
|
||||
|
|
@ -1100,11 +1065,10 @@ func (s *store) writeToImageStore(fn func(store rwImageStore) error) error {
|
|||
return err
|
||||
}
|
||||
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startWriting(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer store.stopWriting()
|
||||
return fn(store)
|
||||
}
|
||||
|
||||
|
|
@ -1126,11 +1090,10 @@ func (s *store) writeToContainerStore(fn func(store rwContainerStore) error) err
|
|||
return err
|
||||
}
|
||||
|
||||
store.Lock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startWriting(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer store.stopWriting()
|
||||
return fn(store)
|
||||
}
|
||||
|
||||
|
|
@ -1151,21 +1114,18 @@ func (s *store) writeToAllStores(fn func(rlstore rwLayerStore, ristore rwImageSt
|
|||
return err
|
||||
}
|
||||
|
||||
rlstore.Lock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startWriting(); err != nil {
|
||||
return err
|
||||
}
|
||||
ristore.Lock()
|
||||
defer ristore.Unlock()
|
||||
if err := ristore.ReloadIfChanged(); err != nil {
|
||||
defer rlstore.stopWriting()
|
||||
if err := ristore.startWriting(); err != nil {
|
||||
return err
|
||||
}
|
||||
rcstore.Lock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
defer ristore.stopWriting()
|
||||
if err := rcstore.startWriting(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer rcstore.stopWriting()
|
||||
|
||||
return fn(rlstore, ristore, rcstore)
|
||||
}
|
||||
|
|
@ -1197,16 +1157,14 @@ func (s *store) PutLayer(id, parent string, names []string, mountLabel string, w
|
|||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
rlstore.Lock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startWriting(); err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
rcstore.Lock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
defer rlstore.stopWriting()
|
||||
if err := rcstore.startWriting(); err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
defer rcstore.stopWriting()
|
||||
if options == nil {
|
||||
options = &LayerOptions{}
|
||||
}
|
||||
|
|
@ -1223,11 +1181,10 @@ func (s *store) PutLayer(id, parent string, names []string, mountLabel string, w
|
|||
for _, l := range append([]roLayerStore{rlstore}, rlstores...) {
|
||||
lstore := l
|
||||
if lstore != rlstore {
|
||||
lstore.RLock()
|
||||
defer lstore.Unlock()
|
||||
if err := lstore.ReloadIfChanged(); err != nil {
|
||||
if err := lstore.startReading(); err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
defer lstore.stopReading()
|
||||
}
|
||||
if l, err := lstore.Get(parent); err == nil && l != nil {
|
||||
ilayer = l
|
||||
|
|
@ -1293,12 +1250,10 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, o
|
|||
var ilayer *Layer
|
||||
for _, s := range layerStores {
|
||||
store := s
|
||||
store.RLock()
|
||||
defer store.Unlock()
|
||||
err := store.ReloadIfChanged()
|
||||
if err != nil {
|
||||
if err := store.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer store.stopReading()
|
||||
ilayer, err = store.Get(layer)
|
||||
if err == nil {
|
||||
break
|
||||
|
|
@ -1481,34 +1436,36 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rlstore.Lock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startWriting(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rlstore.stopWriting()
|
||||
for _, s := range lstores {
|
||||
store := s
|
||||
store.RLock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer store.stopReading()
|
||||
}
|
||||
for _, s := range append([]roImageStore{istore}, istores...) {
|
||||
store := s
|
||||
if store == istore {
|
||||
store.Lock()
|
||||
} else {
|
||||
store.RLock()
|
||||
}
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cimage, err = store.Get(image)
|
||||
if err == nil {
|
||||
imageHomeStore = store
|
||||
break
|
||||
if err := istore.startWriting(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer istore.stopWriting()
|
||||
cimage, err = istore.Get(image)
|
||||
if err == nil {
|
||||
imageHomeStore = istore
|
||||
} else {
|
||||
for _, s := range istores {
|
||||
store := s
|
||||
if err := store.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer store.stopReading()
|
||||
cimage, err = store.Get(image)
|
||||
if err == nil {
|
||||
imageHomeStore = store
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if cimage == nil {
|
||||
|
|
@ -1546,11 +1503,10 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
|
|||
}
|
||||
}
|
||||
} else {
|
||||
rlstore.Lock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startWriting(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rlstore.stopWriting()
|
||||
if !options.HostUIDMapping && len(options.UIDMap) == 0 {
|
||||
uidMap = s.uidMap
|
||||
}
|
||||
|
|
@ -1671,11 +1627,10 @@ func (s *store) Metadata(id string) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cstore.RLock()
|
||||
defer cstore.Unlock()
|
||||
if err := cstore.ReloadIfChanged(); err != nil {
|
||||
if err := cstore.startReading(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer cstore.stopReading()
|
||||
if cstore.Exists(id) {
|
||||
return cstore.Metadata(id)
|
||||
}
|
||||
|
|
@ -1818,11 +1773,10 @@ func (s *store) ImageSize(id string) (int64, error) {
|
|||
}
|
||||
for _, s := range layerStores {
|
||||
store := s
|
||||
store.RLock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startReading(); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer store.stopReading()
|
||||
}
|
||||
|
||||
imageStores, err := s.allImageStores()
|
||||
|
|
@ -1834,11 +1788,10 @@ func (s *store) ImageSize(id string) (int64, error) {
|
|||
var image *Image
|
||||
for _, s := range imageStores {
|
||||
store := s
|
||||
store.RLock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startReading(); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer store.stopReading()
|
||||
if image, err = store.Get(id); err == nil {
|
||||
imageStore = store
|
||||
break
|
||||
|
|
@ -1918,11 +1871,10 @@ func (s *store) ContainerSize(id string) (int64, error) {
|
|||
}
|
||||
for _, s := range layerStores {
|
||||
store := s
|
||||
store.RLock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startReading(); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer store.stopReading()
|
||||
}
|
||||
|
||||
// Get the location of the container directory and container run directory.
|
||||
|
|
@ -1940,11 +1892,10 @@ func (s *store) ContainerSize(id string) (int64, error) {
|
|||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
|
||||
// Read the container record.
|
||||
container, err := rcstore.Get(id)
|
||||
|
|
@ -2002,11 +1953,10 @@ func (s *store) ListContainerBigData(id string) ([]string, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
|
||||
return rcstore.BigDataNames(id)
|
||||
}
|
||||
|
|
@ -2016,11 +1966,10 @@ func (s *store) ContainerBigDataSize(id, key string) (int64, error) {
|
|||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
return rcstore.BigDataSize(id, key)
|
||||
}
|
||||
|
||||
|
|
@ -2029,11 +1978,10 @@ func (s *store) ContainerBigDataDigest(id, key string) (digest.Digest, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
return rcstore.BigDataDigest(id, key)
|
||||
}
|
||||
|
||||
|
|
@ -2042,11 +1990,10 @@ func (s *store) ContainerBigData(id, key string) ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
return rcstore.BigData(id, key)
|
||||
}
|
||||
|
||||
|
|
@ -2083,16 +2030,11 @@ func (s *store) Exists(id string) bool {
|
|||
if err != nil {
|
||||
return false
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return false
|
||||
}
|
||||
if rcstore.Exists(id) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
defer rcstore.stopReading()
|
||||
return rcstore.Exists(id)
|
||||
}
|
||||
|
||||
func dedupeNames(names []string) []string {
|
||||
|
|
@ -2138,11 +2080,10 @@ func (s *store) updateNames(id string, names []string, op updateNameOperation) e
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ristore.Lock()
|
||||
defer ristore.Unlock()
|
||||
if err := ristore.ReloadIfChanged(); err != nil {
|
||||
if err := ristore.startWriting(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer ristore.stopWriting()
|
||||
if ristore.Exists(id) {
|
||||
return ristore.updateNames(id, deduped, op)
|
||||
}
|
||||
|
|
@ -2154,20 +2095,16 @@ func (s *store) updateNames(id string, names []string, op updateNameOperation) e
|
|||
}
|
||||
for _, s := range ristores {
|
||||
store := s
|
||||
store.RLock()
|
||||
defer store.Unlock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
if err := store.startReading(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer store.stopReading()
|
||||
if i, err := store.Get(id); err == nil {
|
||||
if len(deduped) > 1 {
|
||||
// Do not want to create image name in R/W storage
|
||||
deduped = deduped[1:]
|
||||
}
|
||||
_, err := ristore.Create(id, deduped, i.TopLayer, i.Metadata, i.Created, i.Digest)
|
||||
if err == nil {
|
||||
return ristore.Save()
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -2213,11 +2150,10 @@ func (s *store) Names(id string) ([]string, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
if c, err := rcstore.Get(id); c != nil && err == nil {
|
||||
return c.Names, nil
|
||||
}
|
||||
|
|
@ -2251,11 +2187,10 @@ func (s *store) Lookup(name string) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cstore.RLock()
|
||||
defer cstore.Unlock()
|
||||
if err := cstore.ReloadIfChanged(); err != nil {
|
||||
if err := cstore.startReading(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer cstore.stopReading()
|
||||
if c, err := cstore.Get(name); c != nil && err == nil {
|
||||
return c.ID, nil
|
||||
}
|
||||
|
|
@ -2566,11 +2501,10 @@ func (s *store) mount(id string, options drivers.MountOpts) (string, error) {
|
|||
|
||||
s.graphLock.Lock()
|
||||
defer s.graphLock.Unlock()
|
||||
rlstore.Lock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startWriting(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer rlstore.stopWriting()
|
||||
|
||||
modified, err := s.graphLock.Modified()
|
||||
if err != nil {
|
||||
|
|
@ -2646,11 +2580,10 @@ func (s *store) Mounted(id string) (int, error) {
|
|||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rlstore.RLock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startReading(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer rlstore.stopReading()
|
||||
|
||||
return rlstore.Mounted(id)
|
||||
}
|
||||
|
|
@ -2738,9 +2671,7 @@ func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, erro
|
|||
|
||||
for _, s := range layerStores {
|
||||
store := s
|
||||
store.RLock()
|
||||
if err := store.ReloadIfChanged(); err != nil {
|
||||
store.Unlock()
|
||||
if err := store.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if store.Exists(to) {
|
||||
|
|
@ -2748,15 +2679,15 @@ func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, erro
|
|||
if rc != nil && err == nil {
|
||||
wrapped := ioutils.NewReadCloserWrapper(rc, func() error {
|
||||
err := rc.Close()
|
||||
store.Unlock()
|
||||
store.stopReading()
|
||||
return err
|
||||
})
|
||||
return wrapped, nil
|
||||
}
|
||||
store.Unlock()
|
||||
store.stopReading()
|
||||
return rc, err
|
||||
}
|
||||
store.Unlock()
|
||||
store.stopReading()
|
||||
}
|
||||
return nil, ErrLayerUnknown
|
||||
}
|
||||
|
|
@ -2870,11 +2801,10 @@ func (s *store) LayerParentOwners(id string) ([]int, []int, error) {
|
|||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
rlstore.RLock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startReading(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer rlstore.stopReading()
|
||||
if rlstore.Exists(id) {
|
||||
return rlstore.ParentOwners(id)
|
||||
}
|
||||
|
|
@ -2890,16 +2820,14 @@ func (s *store) ContainerParentOwners(id string) ([]int, []int, error) {
|
|||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
rlstore.RLock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startReading(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
defer rlstore.stopReading()
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
container, err := rcstore.Get(id)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
@ -2946,11 +2874,10 @@ func (s *store) Containers() ([]Container, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
|
||||
return rcstore.Containers()
|
||||
}
|
||||
|
|
@ -3014,11 +2941,10 @@ func (al *additionalLayer) PutAs(id, parent string, names []string) (*Layer, err
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rlstore.Lock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startWriting(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rlstore.stopWriting()
|
||||
rlstores, err := al.s.getROLayerStores()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -3028,11 +2954,10 @@ func (al *additionalLayer) PutAs(id, parent string, names []string) (*Layer, err
|
|||
if parent != "" {
|
||||
for _, lstore := range append([]roLayerStore{rlstore}, rlstores...) {
|
||||
if lstore != rlstore {
|
||||
lstore.RLock()
|
||||
defer lstore.Unlock()
|
||||
if err := lstore.ReloadIfChanged(); err != nil {
|
||||
if err := lstore.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer lstore.stopReading()
|
||||
}
|
||||
parentLayer, err = lstore.Get(parent)
|
||||
if err == nil {
|
||||
|
|
@ -3111,11 +3036,10 @@ func (s *store) Container(id string) (*Container, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
|
||||
return rcstore.Get(id)
|
||||
}
|
||||
|
|
@ -3125,11 +3049,10 @@ func (s *store) ContainerLayerID(id string) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
container, err := rcstore.Get(id)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
@ -3146,11 +3069,10 @@ func (s *store) ContainerByLayer(id string) (*Container, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
containerList, err := rcstore.Containers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -3169,11 +3091,10 @@ func (s *store) ContainerDirectory(id string) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
|
||||
id, err = rcstore.Lookup(id)
|
||||
if err != nil {
|
||||
|
|
@ -3194,11 +3115,10 @@ func (s *store) ContainerRunDirectory(id string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
if err := rcstore.ReloadIfChanged(); err != nil {
|
||||
if err := rcstore.startReading(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer rcstore.stopReading()
|
||||
|
||||
id, err = rcstore.Lookup(id)
|
||||
if err != nil {
|
||||
|
|
@ -3264,11 +3184,10 @@ func (s *store) Shutdown(force bool) ([]string, error) {
|
|||
s.graphLock.Lock()
|
||||
defer s.graphLock.Unlock()
|
||||
|
||||
rlstore.Lock()
|
||||
defer rlstore.Unlock()
|
||||
if err := rlstore.ReloadIfChanged(); err != nil {
|
||||
if err := rlstore.startWriting(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rlstore.stopWriting()
|
||||
|
||||
layers, err := rlstore.Layers()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ const (
|
|||
var (
|
||||
defaultStoreOptionsOnce sync.Once
|
||||
loadDefaultStoreOptionsErr error
|
||||
once sync.Once
|
||||
storeOptions StoreOptions
|
||||
storeError error
|
||||
)
|
||||
|
||||
func loadDefaultStoreOptions() {
|
||||
|
|
@ -167,8 +170,8 @@ func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf str
|
|||
return storageOpts, nil
|
||||
}
|
||||
|
||||
// DefaultStoreOptions returns the default storage ops for containers
|
||||
func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
|
||||
// loadStoreOptions returns the default storage ops for containers
|
||||
func loadStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
|
||||
storageConf, err := DefaultConfigFile(rootless && rootlessUID != 0)
|
||||
if err != nil {
|
||||
return defaultStoreOptions, err
|
||||
|
|
@ -176,6 +179,21 @@ func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
|
|||
return defaultStoreOptionsIsolated(rootless, rootlessUID, storageConf)
|
||||
}
|
||||
|
||||
// UpdateOptions should be called iff container engine recieved a SIGHUP,
|
||||
// otherwise use DefaultStoreOptions
|
||||
func UpdateStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
|
||||
storeOptions, storeError = loadStoreOptions(rootless, rootlessUID)
|
||||
return storeOptions, storeError
|
||||
}
|
||||
|
||||
// DefaultStoreOptions returns the default storage ops for containers
|
||||
func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
|
||||
once.Do(func() {
|
||||
storeOptions, storeError = loadStoreOptions(rootless, rootlessUID)
|
||||
})
|
||||
return storeOptions, storeError
|
||||
}
|
||||
|
||||
// StoreOptions is used for passing initialization options to GetStore(), for
|
||||
// initializing a Store object and the underlying storage that it controls.
|
||||
type StoreOptions struct {
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7
|
|||
github.com/containers/ocicrypt/spec
|
||||
github.com/containers/ocicrypt/utils
|
||||
github.com/containers/ocicrypt/utils/keyprovider
|
||||
# github.com/containers/storage v1.43.1-0.20221017123904-a4d4fe98e37d
|
||||
# github.com/containers/storage v1.43.1-0.20221024131621-fae5bbf607fc
|
||||
## explicit; go 1.17
|
||||
github.com/containers/storage
|
||||
github.com/containers/storage/drivers
|
||||
|
|
|
|||
Loading…
Reference in New Issue