The errors returned from Mount and Unmount functions are raw syscall.Errno errors (like EPERM or EINVAL), which provides no context about what has happened and why. Similar to os.PathError type, introduce mount.Error type with some context. The error messages will now look like this: > mount /tmp/mount-tests/source:/tmp/mount-tests/target, flags: 0x1001: operation not permitted or > mount tmpfs:/tmp/mount-test-source-516297835: operation not permitted Before this patch, it was just > operation not permitted [v2: add Cause()] [v3: rename MountError to Error, document Cause()] [v4: fixes; audited all users] [v5: make Error type private; changes after @cpuguy83 reviews] Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> (cherry picked from commit 65331369617e89ce54cc9be080dba70f3a883d1c) Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> Upstream-commit: 7f1c6bf5a745c8faeba695d3556dff4c4ff5f473 Component: engine
75 lines
1.9 KiB
Go
75 lines
1.9 KiB
Go
package mount // import "github.com/docker/docker/pkg/mount"
|
|
|
|
import (
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
const (
|
|
// ptypes is the set propagation types.
|
|
ptypes = unix.MS_SHARED | unix.MS_PRIVATE | unix.MS_SLAVE | unix.MS_UNBINDABLE
|
|
|
|
// pflags is the full set valid flags for a change propagation call.
|
|
pflags = ptypes | unix.MS_REC | unix.MS_SILENT
|
|
|
|
// broflags is the combination of bind and read only
|
|
broflags = unix.MS_BIND | unix.MS_RDONLY
|
|
)
|
|
|
|
// isremount returns true if either device name or flags identify a remount request, false otherwise.
|
|
func isremount(device string, flags uintptr) bool {
|
|
switch {
|
|
// We treat device "" and "none" as a remount request to provide compatibility with
|
|
// requests that don't explicitly set MS_REMOUNT such as those manipulating bind mounts.
|
|
case flags&unix.MS_REMOUNT != 0, device == "", device == "none":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func mount(device, target, mType string, flags uintptr, data string) error {
|
|
oflags := flags &^ ptypes
|
|
if !isremount(device, flags) || data != "" {
|
|
// Initial call applying all non-propagation flags for mount
|
|
// or remount with changed data
|
|
if err := unix.Mount(device, target, mType, oflags, data); err != nil {
|
|
return &mountError{
|
|
op: "mount",
|
|
source: device,
|
|
target: target,
|
|
flags: oflags,
|
|
data: data,
|
|
err: err,
|
|
}
|
|
}
|
|
}
|
|
|
|
if flags&ptypes != 0 {
|
|
// Change the propagation type.
|
|
if err := unix.Mount("", target, "", flags&pflags, ""); err != nil {
|
|
return &mountError{
|
|
op: "remount",
|
|
target: target,
|
|
flags: flags & pflags,
|
|
err: err,
|
|
}
|
|
return err
|
|
}
|
|
}
|
|
|
|
if oflags&broflags == broflags {
|
|
// Remount the bind to apply read only.
|
|
if err := unix.Mount("", target, "", oflags|unix.MS_REMOUNT, ""); err != nil {
|
|
return &mountError{
|
|
op: "remount-ro",
|
|
target: target,
|
|
flags: oflags | unix.MS_REMOUNT,
|
|
err: err,
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|