github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/mount/mount_windows.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package mount
    18  
    19  import (
    20  	"encoding/json"
    21  	"path/filepath"
    22  	"strings"
    23  
    24  	"github.com/Microsoft/hcsshim"
    25  	"github.com/pkg/errors"
    26  )
    27  
    28  var (
    29  	// ErrNotImplementOnWindows is returned when an action is not implemented for windows
    30  	ErrNotImplementOnWindows = errors.New("not implemented under windows")
    31  )
    32  
    33  // Mount to the provided target
    34  func (m *Mount) Mount(target string) error {
    35  	if m.Type != "windows-layer" {
    36  		return errors.Errorf("invalid windows mount type: '%s'", m.Type)
    37  	}
    38  
    39  	home, layerID := filepath.Split(m.Source)
    40  
    41  	parentLayerPaths, err := m.GetParentPaths()
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	var di = hcsshim.DriverInfo{
    47  		HomeDir: home,
    48  	}
    49  
    50  	if err = hcsshim.ActivateLayer(di, layerID); err != nil {
    51  		return errors.Wrapf(err, "failed to activate layer %s", m.Source)
    52  	}
    53  	defer func() {
    54  		if err != nil {
    55  			hcsshim.DeactivateLayer(di, layerID)
    56  		}
    57  	}()
    58  
    59  	if err = hcsshim.PrepareLayer(di, layerID, parentLayerPaths); err != nil {
    60  		return errors.Wrapf(err, "failed to prepare layer %s", m.Source)
    61  	}
    62  	return nil
    63  }
    64  
    65  // ParentLayerPathsFlag is the options flag used to represent the JSON encoded
    66  // list of parent layers required to use the layer
    67  const ParentLayerPathsFlag = "parentLayerPaths="
    68  
    69  // GetParentPaths of the mount
    70  func (m *Mount) GetParentPaths() ([]string, error) {
    71  	var parentLayerPaths []string
    72  	for _, option := range m.Options {
    73  		if strings.HasPrefix(option, ParentLayerPathsFlag) {
    74  			err := json.Unmarshal([]byte(option[len(ParentLayerPathsFlag):]), &parentLayerPaths)
    75  			if err != nil {
    76  				return nil, errors.Wrap(err, "failed to unmarshal parent layer paths from mount")
    77  			}
    78  		}
    79  	}
    80  	return parentLayerPaths, nil
    81  }
    82  
    83  // Unmount the mount at the provided path
    84  func Unmount(mount string, flags int) error {
    85  	var (
    86  		home, layerID = filepath.Split(mount)
    87  		di            = hcsshim.DriverInfo{
    88  			HomeDir: home,
    89  		}
    90  	)
    91  
    92  	if err := hcsshim.UnprepareLayer(di, layerID); err != nil {
    93  		return errors.Wrapf(err, "failed to unprepare layer %s", mount)
    94  	}
    95  	if err := hcsshim.DeactivateLayer(di, layerID); err != nil {
    96  		return errors.Wrapf(err, "failed to deactivate layer %s", mount)
    97  	}
    98  
    99  	return nil
   100  }
   101  
   102  // UnmountAll unmounts from the provided path
   103  func UnmountAll(mount string, flags int) error {
   104  	return Unmount(mount, flags)
   105  }