syscontainer-tools/pkg/mount/mounter_linux.go
taleintervenor dfaef9d393 syscontainer-tools: update license to Mulan PSL v2
reason: update license to Mulan PSL v2

Signed-off-by: taleintervenor <taleintervenor@aliyun.com>
2020-04-27 14:54:17 +08:00

118 lines
3.0 KiB
Go

// Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
// syscontainer-tools is licensed under the Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
// PURPOSE.
// See the Mulan PSL v2 for more details.
// Description: mount operation
// Author: zhangwei
// Create: 2018-01-18
package mount
import (
"fmt"
"path/filepath"
"strings"
"syscall"
docker_mount "github.com/docker/docker/pkg/mount"
)
// Mount is mount operation
func Mount(device, target, mType, options string) error {
flagint, data := docker_mount.ParseOptions(options)
flag := uintptr(flagint)
// propagation option
propagationFlags := (uintptr)(syscall.MS_SLAVE | syscall.MS_SHARED | syscall.MS_UNBINDABLE | syscall.MS_PRIVATE)
if err := syscall.Mount(device, target, mType, flag&^propagationFlags, data); err != nil {
return err
}
// If we have a bind mount or remount, remount...
if flag&syscall.MS_BIND == syscall.MS_BIND && flag&syscall.MS_RDONLY == syscall.MS_RDONLY {
return syscall.Mount(device, target, mType, flag|syscall.MS_REMOUNT, data)
}
if flag&propagationFlags != 0 {
return syscall.Mount("none", target, "none", flag&propagationFlags, data)
}
return nil
}
// Unmount is unmount operation
func Unmount(target string) error {
return syscall.Unmount(target, syscall.MNT_DETACH)
}
// ValidMountPropagation checks propagation of path
func ValidMountPropagation(path, mOpt string) error {
var bind, slave, shared bool
var slavemnt, sharedmnt bool
for _, opt := range strings.Split(mOpt, ",") {
if opt == "bind" {
bind = true
}
if opt == "shared" {
shared = true
}
if opt == "slave" {
slave = true
}
}
if !bind {
return nil
}
source, options, err := getSource(path)
if err != nil {
return err
}
for _, opt := range strings.Split(options, " ") {
if strings.HasPrefix(opt, "shared:") {
sharedmnt = true
break
}
if strings.HasPrefix(opt, "master:") {
slavemnt = true
break
}
}
if shared && !sharedmnt {
return fmt.Errorf("Path %s is mounted on %s but it is not a shared mount", path, source)
}
if slave && !sharedmnt && !slavemnt {
return fmt.Errorf("Path %s is mounted on %s but it is not a shared or slave mount", path, source)
}
return nil
}
func getSource(sourcepath string) (string, string, error) {
path, err := filepath.EvalSymlinks(sourcepath)
if err != nil {
return "", "", err
}
mountinfos, err := docker_mount.GetMounts()
if err != nil {
return "", "", err
}
for {
for _, m := range mountinfos {
if m.Mountpoint == path {
return path, m.Optional, nil
}
}
if path == "/" {
return "", "", fmt.Errorf("Could not find mount %s", sourcepath)
}
path = filepath.Dir(path)
}
return "", "", fmt.Errorf("Unexpected error in getMouont")
}