1package mount // import "github.com/docker/docker/pkg/mount"
2
3import (
4	"golang.org/x/sys/unix"
5)
6
7const (
8	// ptypes is the set propagation types.
9	ptypes = unix.MS_SHARED | unix.MS_PRIVATE | unix.MS_SLAVE | unix.MS_UNBINDABLE
10
11	// pflags is the full set valid flags for a change propagation call.
12	pflags = ptypes | unix.MS_REC | unix.MS_SILENT
13
14	// broflags is the combination of bind and read only
15	broflags = unix.MS_BIND | unix.MS_RDONLY
16)
17
18// isremount returns true if either device name or flags identify a remount request, false otherwise.
19func isremount(device string, flags uintptr) bool {
20	switch {
21	// We treat device "" and "none" as a remount request to provide compatibility with
22	// requests that don't explicitly set MS_REMOUNT such as those manipulating bind mounts.
23	case flags&unix.MS_REMOUNT != 0, device == "", device == "none":
24		return true
25	default:
26		return false
27	}
28}
29
30func mount(device, target, mType string, flags uintptr, data string) error {
31	oflags := flags &^ ptypes
32	if !isremount(device, flags) || data != "" {
33		// Initial call applying all non-propagation flags for mount
34		// or remount with changed data
35		if err := unix.Mount(device, target, mType, oflags, data); err != nil {
36			return err
37		}
38	}
39
40	if flags&ptypes != 0 {
41		// Change the propagation type.
42		if err := unix.Mount("", target, "", flags&pflags, ""); err != nil {
43			return err
44		}
45	}
46
47	if oflags&broflags == broflags {
48		// Remount the bind to apply read only.
49		return unix.Mount("", target, "", oflags|unix.MS_REMOUNT, "")
50	}
51
52	return nil
53}
54
55func unmount(target string, flag int) error {
56	return unix.Unmount(target, flag)
57}
58