6533136961
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>
59 lines
1.2 KiB
Go
59 lines
1.2 KiB
Go
package mount // import "github.com/docker/docker/pkg/mount"
|
|
|
|
/*
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/_iovec.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/param.h>
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"strings"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
func allocateIOVecs(options []string) []C.struct_iovec {
|
|
out := make([]C.struct_iovec, len(options))
|
|
for i, option := range options {
|
|
out[i].iov_base = unsafe.Pointer(C.CString(option))
|
|
out[i].iov_len = C.size_t(len(option) + 1)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func mount(device, target, mType string, flag uintptr, data string) error {
|
|
isNullFS := false
|
|
|
|
xs := strings.Split(data, ",")
|
|
for _, x := range xs {
|
|
if x == "bind" {
|
|
isNullFS = true
|
|
}
|
|
}
|
|
|
|
options := []string{"fspath", target}
|
|
if isNullFS {
|
|
options = append(options, "fstype", "nullfs", "target", device)
|
|
} else {
|
|
options = append(options, "fstype", mType, "from", device)
|
|
}
|
|
rawOptions := allocateIOVecs(options)
|
|
for _, rawOption := range rawOptions {
|
|
defer C.free(rawOption.iov_base)
|
|
}
|
|
|
|
if errno := C.nmount(&rawOptions[0], C.uint(len(options)), C.int(flag)); errno != 0 {
|
|
return &mountError{
|
|
op: "mount",
|
|
source: device,
|
|
target: target,
|
|
flags: flag,
|
|
err: syscall.Errno(errno),
|
|
}
|
|
}
|
|
return nil
|
|
}
|